如何制作通用函数 C
How to make a generic function C
我必须创建一个 HashMap。我创建了两个结构。一个 node struct
和一个 table struct
。第二个结构将“包含”我的节点。我的问题是 insert
函数:我必须插入我的 table (*t) 对 (key,value)。问题是键和值类型必须是通用的。所以,我想插入 int、double、char、ecc.. 如何将我的函数变成 generic function?
insert.c
struct node{
int key;
int val;
struct node *next;
struct node *prev;
};
struct table{
int size;
struct node **list;
};
int hashCode(int key){
if(key>0)
return key-1;
return key+1;
}
void insert(struct table *t,int key,int val){
int pos = hashCode(key);
struct node *list = t->list[pos];
struct node *newNode = (struct node*)malloc(sizeof(struct node));
struct node *temp = list;
while(temp){
if(temp->key==key){
printf("%s", "Key already created");
return;
}
temp = temp->next;
}
newNode->next = list;
newNode->key = key;
newNode->val = val;
if(list!=NULL){
list->prev = newNode;
}
t->list[pos] = newNode;
newNode->prev = NULL;
}
main.c
int main(){
struct table *t = /* I create the structure */ ;
insert(t,2,3);
insert(t,3,4);
insert(t,2,3);
// insert(t,'a','c'); function insert should execute also with char, int, float, double ecc...
return 0;
}
从 C11 开始您可以使用 _Generic
#include <stdio.h>
#define hashCode(x) _Generic((x), \
int: hash_int, \
double: hash_double \
)(x)
int hash_int(int value)
{
printf("Hashing %d\n", value);
return 42;
}
int hash_double(double value)
{
printf("Hashing %f\n", value);
return 42;
}
int main(void)
{
hashCode(3);
hashCode(3.14);
return (0);
}
说明
Provides a way to choose one of several expressions at compile time,
based on a type of a controlling expression
First, the type of controlling-expression undergoes lvalue
conversions. The conversion is performed in type domain only: it
discards the top-level cvr-qualifiers and atomicity and applies
array-to-pointer/function-to-pointer transformations to the type of
the controlling expression, without initiating any side-effects or
calculating any values.
The type after conversion is compared with type-names from the list of
associations.
If the type is compatible with the type-name of one of the
associations, then the type, value, and value category of the generic
selection are the type, value, and value category of the expression
that appears after the colon for that type-name.
If none of the type-names are compatible with the type of the
controlling-expression, and the default association is provided, then
the type, value, and value category of the generic selection are the
type, value, and value category of the expression after the default :
label.
你这样定义并集:
union value {
int i;
float f;
char c;
//and so on
};
你的节点是这样的:
struct node{
int key;
union value val;
struct node *next;
struct node *prev;
};
你像这样改变你的函数参数:
void insert(struct table *t, int key, union value val) {}
而你的 main 变成了(我使用宏来简化联合的创建):
#define UVAL(v, k) (union value){ .k = v}
int main(){
struct table * t = NULL; //Todo
insert(t, 2, UVAL(3, i) );
insert(t, 3, UVAL(4, i));
insert(t, 2, UVAL(3, i));
return 0;
}
用一些花车代替:
int main(){
struct table * t = NULL; //Todo
insert(t, 2, UVAL(3.5f, f));
insert(t, 3, UVAL(4.f, f));
insert(t, 2, UVAL(3.5f, f));
return 0;
}
我必须创建一个 HashMap。我创建了两个结构。一个 node struct
和一个 table struct
。第二个结构将“包含”我的节点。我的问题是 insert
函数:我必须插入我的 table (*t) 对 (key,value)。问题是键和值类型必须是通用的。所以,我想插入 int、double、char、ecc.. 如何将我的函数变成 generic function?
insert.c
struct node{
int key;
int val;
struct node *next;
struct node *prev;
};
struct table{
int size;
struct node **list;
};
int hashCode(int key){
if(key>0)
return key-1;
return key+1;
}
void insert(struct table *t,int key,int val){
int pos = hashCode(key);
struct node *list = t->list[pos];
struct node *newNode = (struct node*)malloc(sizeof(struct node));
struct node *temp = list;
while(temp){
if(temp->key==key){
printf("%s", "Key already created");
return;
}
temp = temp->next;
}
newNode->next = list;
newNode->key = key;
newNode->val = val;
if(list!=NULL){
list->prev = newNode;
}
t->list[pos] = newNode;
newNode->prev = NULL;
}
main.c
int main(){
struct table *t = /* I create the structure */ ;
insert(t,2,3);
insert(t,3,4);
insert(t,2,3);
// insert(t,'a','c'); function insert should execute also with char, int, float, double ecc...
return 0;
}
从 C11 开始您可以使用 _Generic
#include <stdio.h>
#define hashCode(x) _Generic((x), \
int: hash_int, \
double: hash_double \
)(x)
int hash_int(int value)
{
printf("Hashing %d\n", value);
return 42;
}
int hash_double(double value)
{
printf("Hashing %f\n", value);
return 42;
}
int main(void)
{
hashCode(3);
hashCode(3.14);
return (0);
}
说明
Provides a way to choose one of several expressions at compile time, based on a type of a controlling expression
First, the type of controlling-expression undergoes lvalue conversions. The conversion is performed in type domain only: it discards the top-level cvr-qualifiers and atomicity and applies array-to-pointer/function-to-pointer transformations to the type of the controlling expression, without initiating any side-effects or calculating any values.
The type after conversion is compared with type-names from the list of associations.
If the type is compatible with the type-name of one of the associations, then the type, value, and value category of the generic selection are the type, value, and value category of the expression that appears after the colon for that type-name.
If none of the type-names are compatible with the type of the controlling-expression, and the default association is provided, then the type, value, and value category of the generic selection are the type, value, and value category of the expression after the default : label.
你这样定义并集:
union value {
int i;
float f;
char c;
//and so on
};
你的节点是这样的:
struct node{
int key;
union value val;
struct node *next;
struct node *prev;
};
你像这样改变你的函数参数:
void insert(struct table *t, int key, union value val) {}
而你的 main 变成了(我使用宏来简化联合的创建):
#define UVAL(v, k) (union value){ .k = v}
int main(){
struct table * t = NULL; //Todo
insert(t, 2, UVAL(3, i) );
insert(t, 3, UVAL(4, i));
insert(t, 2, UVAL(3, i));
return 0;
}
用一些花车代替:
int main(){
struct table * t = NULL; //Todo
insert(t, 2, UVAL(3.5f, f));
insert(t, 3, UVAL(4.f, f));
insert(t, 2, UVAL(3.5f, f));
return 0;
}