GCC4.7+中如何替代C11中的_Generic

GCC4.7+中如何替代C11中的_Generic

C11标准中,一个非常重大的特性更新就是增加了Generic Selection这个特性。这个特性能使得C11支持轻量级的泛型编程,使得可以把一组具有不同类型而却有相同功能的函数抽象为一个接口。

对于_Generic的使用可参见俺这篇博文——http://www.cnblogs.com/zenny-chen/archive/2012/09/20/2695381.html


由于GCC至今还没有支持C11标准的Generic Selection,不过GCC似乎从4.0版本开始就支持了一些内建的编译时函数(这些函数类似于sizeof),包括比较常见的typeof。这里,我们通过组合使用__builtin_choose_expr以及__builtin_types_compatible_p就可实现C11的Generic Selection功能。

我们先看一下__builtin_choose_expr的原型:

type __builtin_choose_expr (const_exp, exp1, exp2)

这里要注意的是这个函数的第一个参数必须是常量表达式,因为之前我已经说过,它属于编译时行为,而非运行时行为,跟sizeof和typeof一样。这个函数是一个谓词函数,如果const_expr的结果非0,那么生成exp1,且返回类型type也与exp1表达式的类型一致;否则生成exp2,并且返回类型type也与exp2的类型一致。由于是编译时行为,因此exp1与exp2表达式所产生的目标代码是互斥的,生成了exp1就不会存在exp2。下面举一个简单例子:

复制代码
int main(void)
{
    (void)__builtin_choose_expr(100 < 1000, puts("OK"), puts("NG"));

    int a = __builtin_choose_expr(sizeof('a') == 1, "YES", 100);
    printf("The value is: %d\n", a);
}
复制代码


然后,我们再看一下编译时内建函数__builtin_types_compatible_p,其原型为——

int __builtin_types_compatible_p (type1, type2)

这个函数是比较type1与type2两个类型(注意,这里是类型,而不是表达式),如果两个类型的非限定版本相兼容,那么返回1,否则返回0。这里也举个简单的例子:

复制代码
int main(void)
{
    int r = __builtin_types_compatible_p(typeof('a'), char);
    printf("result 1 is: %d\n", r);
    
    r = __builtin_types_compatible_p(typeof('a'), const int);
    printf("result 2 is: %d\n", r);
}
复制代码


好。介绍完了这两个编译时内建函数之后,我们就来看看如何将它们组合起来以实现C11 Generic Selection的功能:

复制代码
int main(void)
{
    _Generic('a', int:puts("WOW"), char:puts("Ja~~"), default:puts("Oui~~"));

    // equivalent
    (void)__builtin_choose_expr(__builtin_types_compatible_p(typeof('a'), int), puts("WOW"),
                                __builtin_choose_expr(__builtin_types_compatible_p(typeof('a'), char), puts("Ja~~"), puts("Oui~~")));
}
复制代码

 

这里要注意的是,使用这些内建函数必须开启GNU规范,4.7以上版本的GCC可直接用C11标准了,开启方法为:在命令选项中添加-std=gnu11

转自:http://www.cnblogs.com/zenny-chen/p/3303560.html

2011年12月8日,ISO正式发布了新的C语言的新标准C11,之前被称为C1X,官方名称为ISO/IEC 9899:2011。 新的标准提高了对C++的兼容性,并增加了一些新的特性。这些新特性包括: 对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符, aligned_alloc函数以及<stdalign.h>头文件。 _Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。 _Generic 关键字。 多线程(Multithreading)支持,包括:_Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。 增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>. 删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。 增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。 增加了更多浮点处理宏。 匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。 静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。 新的 fopen() 模式,(“…x”)。类似 POSIX 的 O_CREAT|O_EXCL,在文件锁比较常用。 新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。 _Atomic类型修饰符和<stdatomic.h>头文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值