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. 宝塔 + 阿里云ECS + MySql + Navicat 远程连接数据库

    宝塔 + 阿里云ECS + MySql + Navicat 远程连接 1. root登录: 2.  grant all privileges on *.* to root@'%' identified ...

  2. 【url ---lib___】笔趣阁(抓取斗罗大陆完整)和(三寸天堂)

    # coding=gbk #因为在黑屏下执行,所以代码会使用GBK url='http://www.biquge.info/10_10218/' UA={"User-Agent": ...

  3. EasyUI+JSP之java读取数据库后JSON格式数据的返回及调用

    做作业工程中遇到一些问题,特此记录一下 解决的问题:使用EasyUI框架搭建简单学生管理系统(数据库增删改查)操作时配合JSP,不知道如何把从数据库获得的数据封装成JSON格式并传回前端JSP并进行展 ...

  4. golang shell 交叉编译

    #!/usr/bin/env bash set -e uname_s=`uname -s | awk '{print tolower($0)}'` uname_m=`uname -m` timeTag ...

  5. HashMap源码分析二

    jdk1.2中HashMap的源码和jdk1.3中HashMap的源码基本上没变.在上篇中,我纠结的那个11和101的问题,在这边中找到答案了.   jdk1.2   public HashMap() ...

  6. CSS基础学习 19.CSS hack

  7. [转载]ac mysql 无法远程连接

    Mac mysql 无法远程连接 2018年07月23日 10:56:02 feixiang2039 阅读数 2866   版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附 ...

  8. ACM-ICPC 2018 青岛赛区网络预赛 J. Press the Button(数学)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4056 题意:有一个按钮,时间倒计器和计数器,在时间[0,t]内, ...

  9. 洛谷P1363 幻想迷宫【dfs】

    题目:https://www.luogu.org/problemnew/show/P1363 题意: 有一个地图,起点是S,障碍物用#表示.可以将这个地图不断的在四周重复,问从起点开始是否可以走到无限 ...

  10. JDBC (Java DataBase Connectivity)数据库连接池原理解析与实现

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...