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

GCC4.7+中如何替代C11中的_Generic的更多相关文章

  1. C11中的Unicode

    在C11(ISO/IEC 9899:2011)标准中引入了对UTF8.UTF16以及UTF32字符编码的支持. 其中,UTF8字符直接通过char来定义,字面量前缀使用u8.比如: char c = ...

  2. MySQL 5.7中 performance_schema 替代 show profile 命令

    本文出处:http://www.cnblogs.com/wy123/p/6979499.html show profile 命令用于跟踪执行过的sql语句的资源消耗信息,可以帮助查看sql语句的执行情 ...

  3. MySQL的show profile(已过时)简介以及该功能在MySQL 5.7中performance_schema中的替代

    本文出处:http://www.cnblogs.com/wy123/p/6979499.html show profile 命令用于跟踪执行过的sql语句的资源消耗信息,可以帮助查看sql语句的执行情 ...

  4. 理解性能的奥秘——应用程序中慢,SSMS中快(6)——SQL Server如何编译动态SQL

    本文属于<理解性能的奥秘--应用程序中慢,SSMS中快>系列 接上文:理解性能的奥秘--应用程序中慢,SSMS中快(5)--案例:如何应对参数嗅探 我们抛开参数嗅探的话题,回到了本系列的最 ...

  5. WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探

    原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探         最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感 ...

  6. 排坑&#183;IPhone&IOS中不兼容正则中的断言匹配

    阅文时长 | 1.14分钟 字数统计 | 1834.4字符 主要内容 | 1.问题切入 2.什么是断言匹配 3.断言匹配的替换方案 4.声明与参考资料 『排坑·IPhone&IOS中不兼容正则 ...

  7. Firebug中调试中的js脚本中中文内容显示为乱码

    Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...

  8. JavaScript中让Html页面中循环播放文字

    JavaScript中让Html页面中循环播放文字 <html> <head> <meta http-equiv="Content-Type" con ...

  9. PHP中如何在数组中随机抽取n个数据的值 - array_rand()?

    PHP中如何在数组中随机抽取n个数据的值? 最佳答案 array_rand() 在你想从数组中取出一个或多个随机的单元时相当有用.它接受 input 作为输入数组和一个可选的参数 num_req,指明 ...

随机推荐

  1. mysql 5.6.38 数据库编译安装

    一.系统环境: # cat /etc/redhat-release CentOS release 6.9 (Final) 二.mysql 编译安装: 1.安装依赖包: yum install -y n ...

  2. 车型识别API调用与批量分类车辆图片

    版权声明:本文为博主原创文章,转载 请注明出处 https://blog.csdn.net/sc2079/article/details/82189824 9月9日更:博客资源下载:链接: https ...

  3. RxJava——响应式编程

    自从06年开始,Rxandroid公司项目中陆续就开始使用它了,而它的基础是由Rxjava演变过来的,如今它也是越来越被广泛使用在商业项目中了,而做为"专业"的自己还是一直对它一知 ...

  4. jsp的标签库

    Java Server Pages Standard Tag Libray(JSTL):JSP 标准标签库,是一个定制标签类库的集合,用于解决一些常见的问题,例如迭代一个映射或者集合.条件测试.XML ...

  5. 【转】高可用Redis(六):瑞士军刀之bitmap,HyperLoglog和GEO

    1.bitmap位图 1.1 bitmap位图的概念 首先来看一个例子,字符串big, 字母b的ASCII码为98,转换成二进制为 01100010 字母i的ASCII码为105,转换成二进制为 01 ...

  6. python: json模块 --JSON编码和解码

    json 源代码: Lib/json/__init__.py json.dump() import json numbers = [1, 2, 3, 4] with open('linshi.py', ...

  7. mysql 5.6zip版本的卸载与5.7 zip 版本的安装

    链接:http://www.imooc.com/article/10359 一 安装环境windows 7 旗舰版mysql-5.6.17-winx64.zip 二 安装过程1.去官网下载mysql- ...

  8. Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化

    引言 在数据库存在外键的其情况下,使用select_related()和prefetch_related()很大程度上减少对数据库的请求次数以提高性能 1.实例准备 模型: from django.d ...

  9. 长春理工大学第十四届程序设计竞赛H Arithmetic Sequence——使用特例

    题目 链接 题意:给定一个数X,输出一个等差数列,使得和为X. 分析 由等差数列的定义,可见一个数就是等差数列,两个数也是等差数列 #include<bits/stdc++.h> usin ...

  10. TabSheet源码

    TabSheet.h #if !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_) #define AFX ...