Stay Hungry.Stay Foolish.
c语言中泛型的使用

c语言里面使用泛型,高版本clang和gcc都支持。

问题出发点

一直想要用c实现一个比较好操作的hashtable,类似这种接口hash_table_insert(hashtable, key, value), 网上大家的实现都是声明key,value参数为void *, 这样的操作个人感觉非常麻烦,我想要的是使用者无需关心key和value的类型,直接插入,变得和动态类型语言一样。

解决方法

c没有java, C++那种泛型模板,也不像动态语言变量可以无需指定类型,然后我搜索发现c11标准已经加入了generics, gcc和clang编译器已经提供_Generic这个宏,vs不支持,因为vs好像宣布永远只支持c89,不会再改进了,具体可以参考这里学习,可以识别参数的类型,那么问题就解决了! 使用起来非常简单,下面是我在我实现的hashtable中定义的宏

#define hash_table_insert(table, key, value) _Generic((value),\
    _Bool: hash_table_insert_bool, \
    short int: hash_table_insert_long, \
    unsigned short int: hash_table_insert_long, \
    int: hash_table_insert_long, \
    unsigned int: hash_table_insert_long, \
    long int: hash_table_insert_long, \
    unsigned long int: hash_table_insert_long, \
    long long int: hash_table_insert_long, \
    unsigned long long int: hash_table_insert_long, \
    float: hash_table_insert_double, \
    double: hash_table_insert_double, \
    char *: hash_table_insert_string, \
    default: unsupport_type)((table), (key), (value))

科普

使用的时候,比如像我这个接口,最好就是显示指定值得类型,就像下面这样,否者可能得不到你预期的结果

 char *a = "hello";
    bool b = true;
    long c = 1;
    double d = 1.1;
    char e = 'c';
    hash_table_insert(hashtable, "string", a);
    hash_table_insert(hashtable, "bool", b);
    hash_table_insert(hashtable, "long", c);
    hash_table_insert(hashtable, "double", d);
    hash_table_insert(hashtable, "unsupport type", e);
    hash_table_print(hashtable);

因为如果你直接使用true去尝试插入,本质上true和false在stdbool.h中的定义是宏,值是0和1,0和1在c语言默认不指定类型是int,而不是你想插入的bool类型了。

疑问,待解决

编译器是使用啥黑科技判断类型的?我自己只能想到类型字长,在64位系统上,比如char的sizeof是1,int是4, char *是8,但是如果再来个void *或者long,都是8个字节的长度,就无法解决了,知道的欢迎留言!

自由转载-非商用-非衍生-保持署名(创意共享3.0许可证
评论

暂无评论~~