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( < , puts("OK"), puts("NG")); int a = __builtin_choose_expr(sizeof('a') == , "YES", );
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

最新文章

  1. Attribute富文本使用方法
  2. MongoDB-3.2.6 副本集 和主从
  3. json返回数据库的时间格式为/Date(1477294037000)/,怎样在前台进行格式化转换
  4. (基础篇)php中理解print EOT分界符和echo EOT的用法区别
  5. (旧)子数涵数&#183;C语言——让C帮你做计算
  6. Jpush推送模块
  7. VS2013控制台一闪而过问题解决方法
  8. Docker进入主流,PaaS大有可为(转)
  9. python备忘录
  10. 什么是JSON?如何使用?它比BSON更好吗?
  11. java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解(勿删)
  12. Android 事件统计
  13. day09&lt;面向对象+&gt;
  14. 29.Django session
  15. nysql报错1136
  16. 音频格式RAW和PCM区别和联系
  17. maven里面pom文件的各标签介绍
  18. Android之Activity与fragment完整生命周期图
  19. 如何使用python来对二维数组进行排序
  20. ES6的新特性(13)——Symbol

热门文章

  1. 【转载】interpolation(插值)和 extrapolation(外推)的区别
  2. Linux基础篇之CentOS的网络配置(DHCP,静态)
  3. 循环遍历 文件夹 生成makefile
  4. 构建之法第二次作业【使用git和Vs实现四则运算】
  5. P1361 小M的作物 最小割理解
  6. JavaScript教程——this 关键字
  7. IE的F12开发人员工具不显示 转载自:http://blog.csdn.net/longyulu/article/details/8749705
  8. asp.net 各种文件解析探索
  9. docker化hbase并使用外部zookeeper
  10. MFC GDI绘图