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( < , 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的更多相关文章
- C11中的Unicode
在C11(ISO/IEC 9899:2011)标准中引入了对UTF8.UTF16以及UTF32字符编码的支持. 其中,UTF8字符直接通过char来定义,字面量前缀使用u8.比如: char c = ...
- MySQL 5.7中 performance_schema 替代 show profile 命令
本文出处:http://www.cnblogs.com/wy123/p/6979499.html show profile 命令用于跟踪执行过的sql语句的资源消耗信息,可以帮助查看sql语句的执行情 ...
- MySQL的show profile(已过时)简介以及该功能在MySQL 5.7中performance_schema中的替代
本文出处:http://www.cnblogs.com/wy123/p/6979499.html show profile 命令用于跟踪执行过的sql语句的资源消耗信息,可以帮助查看sql语句的执行情 ...
- 理解性能的奥秘——应用程序中慢,SSMS中快(6)——SQL Server如何编译动态SQL
本文属于<理解性能的奥秘--应用程序中慢,SSMS中快>系列 接上文:理解性能的奥秘--应用程序中慢,SSMS中快(5)--案例:如何应对参数嗅探 我们抛开参数嗅探的话题,回到了本系列的最 ...
- WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探
原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探 最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感 ...
- 排坑·IPhone&IOS中不兼容正则中的断言匹配
阅文时长 | 1.14分钟 字数统计 | 1834.4字符 主要内容 | 1.问题切入 2.什么是断言匹配 3.断言匹配的替换方案 4.声明与参考资料 『排坑·IPhone&IOS中不兼容正则 ...
- Firebug中调试中的js脚本中中文内容显示为乱码
Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...
- JavaScript中让Html页面中循环播放文字
JavaScript中让Html页面中循环播放文字 <html> <head> <meta http-equiv="Content-Type" con ...
- PHP中如何在数组中随机抽取n个数据的值 - array_rand()?
PHP中如何在数组中随机抽取n个数据的值? 最佳答案 array_rand() 在你想从数组中取出一个或多个随机的单元时相当有用.它接受 input 作为输入数组和一个可选的参数 num_req,指明 ...
随机推荐
- 【python+selenium】selenium grid(分布式)
前言 原文:https://blog.csdn.net/real_tino/article/details/53467406 Selenium grid是用来分布式执行测试用例脚本的工具,比如测试人员 ...
- Kubernetes的初始化容器initContainers
initContainers是一种专用的容器,在应用程序容器启动之前运行,可以包括一些应用程序镜像中不存在的实用工具和安装脚本,可以完成应用的必要数据初始化等工作.总的来说就是在正式的容器启动之前做一 ...
- PAT乙级1041
题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805281567916032 题解 简单的信息录入和查询而已. ...
- [转载]springboot--常用注解--@configration、@Bean
springboot--常用注解--@configration.@Bean @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME ...
- 定时备份etc目录
#!/bin/bash # #******************************************************************** #encoding -*-utf ...
- Appium真机运行测试用例
- ACM省赛及蓝桥总结,且随疾风前行,身后亦须留心
今年算是开始正式打比赛了,真正打起比赛来感觉的确是和平时训练不太一样,最重要的还是在心态和信心上. ACM省赛是拿下个银牌,昭哥上来就把K题金牌题给当签到题给签掉了,可惜我们没有利用好这一题.感觉第一 ...
- linux系统nginx下反向代理解析二级目录泛目录教程
解析规则1: location /目录名 { proxy_pass http://ip/目录名; } 解析规则2: location /目录名{ ...
- 正则匹配href标签内容
完整a标签 <a.+?href=\"(.+?)\".*>(.+)</a> 单独href : <a.+?href=\"(.+?)\" ...
- C++ #include<algorithm>
今天下午大致学完了进阶指南中algorithm头文件下的内容,在这里进行一个总结. reverse翻转 顾名思义,reverse进行的操作就是翻转原来的顺序,理解非常简单,故不赘述. 操作样例 ...