GCC和Clang的两个值得了解的编译器开关
GCC和Clang的两个值得了解的编译器开关,在系统编程中非常有用。
-fno-strict-aliasing
禁止依赖于严格别名规则的优化。严格别名规则指的是两个不相关类型的指针解引用不会相互影响,一个例外是(signed/unsigned) char指针解引用会与任何其它指针解引用互相影响。
遵守严格别名规则的话,只能使用memcpy或char*互拷进行数据重解析,有些代码实现起来性能肯定会大打折扣。比如如果开启严格别名规则优化的话,memcpy高效C/C++语言inline实现只能转换为char*然后期待编译器给你进行循环展开,如果转换为int*企图手动实现循环展开,可能会被优化掉导致程序跑飞。
-fwrapv
将有符号数溢出定义为2的补码回卷,禁止依赖于有符号数溢出是未定义行为的优化。假定有符号数溢出是未定义行为的优化会优化掉手工检测溢出的代码,因此如果需要手工检测溢出,是需要关闭相关优化的。
这两个开关很多软件都在用,Linux内核在使用-fno-strict-aliasing,很多编程语言和数据库等系统软件也在使用-fwrapv。
GCC和Clang在-O2、-O3、-Os、-Ofast优化级别默认会开启相关优化,所以需要使用这两个开关关掉这些优化。
# 不开优化
gcc -o prog prog.c
# 开-O2优化,不相关类型指针解引用、有符号数溢出可能被优化掉
gcc -O2 -o prog prog.c
# 开-O2优化,不优化不相关类型指针解引用、有符号数溢出
gcc -O2 -fno-strict-aliasing -fwrapv -o prog proc.c
【参考资料】
下面的文章介绍了Linus对于这两个特性的口水战:
https://zine.la/article/686f5e1e554a4f439bef689005771519/
https://www.oschina.net/news/96906/linus-was-angry-about-standard-saying?p=1
下面的文章介绍了Clang是如何看待和处理未定义行为的:
https://blog.csdn.net/monkey07118124/article/details/50588336
https://www.cnblogs.com/foohack/p/3582239.html
【严格别名规则的示例】
#include <stdio.h>
void check1(short *h, long *k)
{*h = 5;*k = 6; // 编译器认为不会改变*hif (*h == 5)printf("strict aliasing problem 1\n");
}
void check2(short *h, char *k)
{*h = 5;*k = 6; // 编译器认为可能改变*hif (*h == 5)printf("strict aliasing problem 2\n");
}
void check3(short *h, char *k)
{*h = 5;*(int*)k = 6; // 编译器仍然认为不会改变*hif (*h == 5)printf("strict aliasing problem 3\n");
}
void check4(char *h, short *k)
{*h = 5;*k = 6; // 编译器认为可能改变*hif (*h == 5)printf("strict aliasing problem 4\n");
}
int main()
{long k[1] = { 0 };check1((short *)k, (long *)k);check2((short *)k, (char *)k);check3((short *)k, (char *)k);check4((char *)k, (short *)k);
}
【有符号数溢出的示例】
#include <stdio.h>
void testoverflow(int a)
{if (a + 1 < a) // 编译器认为总是falseprintf("overflow\n");
}
GCC和Clang的两个值得了解的编译器开关相关推荐
- gcc、clang、make、cmake、makefile、CMakeLists.txt概念学习
说明 编译器是翻译代码为计算机语言的一个工具,我们平时写的代码如果想在某个特定的计算机上执行(计算机的cpu构架不同),就需要编译器来对代码进行编译汇编链接,而汇编和链接的过程对于每个不同的平台上过程 ...
- 编译器GCC与Clang的异同
GCC:GNU(Gnu's Not Unix)编译器套装(GNU Compiler Collection,GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键 ...
- 电脑word文档打不开怎么办_word怎么转pdf?两个值得学习的高效转换法
word怎么转pdf?两个值得学习的高效转换法 word怎么转pdf?pdf格式是我们经常能够使用到的格式,因为pdf格式在传递的过程中能更好地避免文件出现乱码打不开或误触导致文件被修改的情况.那如果 ...
- word打开老是配置进度_word怎么转pdf?两个值得学习的高效转换法
word怎么转pdf?两个值得学习的高效转换法 word怎么转pdf?pdf格式是我们经常能够使用到的格式,因为pdf格式在传递的过程中能更好地避免文件出现乱码打不开或误触导致文件被修改的情况.那如果 ...
- 麦芒9不支持鸿蒙系统,盘点两款值得选择和两款不值得选择的华为手机!
众所周知,华为已经连续五年成为国内手机销量之王,取得成功的背后,和它源源不断的研发投入有密不可分的关系.如果华为一直都止步不前的话,那么发展的势头肯定没有现在这么猛烈,华为不仅带来了鸿蒙系统,还研发了 ...
- clang编译c语言开o优化,针对gcc或clang的LTO可以跨C和C方法进行优化
是! 链接时优化通常适用于"胖"目标文件中存在的中间表示(IR),其可以包含用于传统链接的机器代码和用于LTO链接的IR. 在这个阶段,没有更高级的语言结构,因此链接时优化与语言无 ...
- linux int64_t 头文件,这对int64_t的处理是GCC和Clang的错误吗?
你不需要去POSIX对它进行排序,ISO C控制这个特定的方面(下面的参考是C11标准). 这个答案的其余部分将成为所有"语言律师",以显示为什么将未添加的行为添加到已签名的值中, ...
- gcc/g++/clang/cl编译器
编译器一般构成 传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd).在编译过程中,前端主要负责词法和语法分析,将源代码转化为抽象语法树:优化器 ...
- java程序中出现两个class,Java中Class类中两个值得注意的进行类型动态转换的方法...
Java中的Class类有两个重要的方法:cast()和asSubclass().这两个方法都是用于Class类进行运行时(run-time)阶段的类型转换的.下面来看看他们的定义和使用: 第一个方法 ...
最新文章
- 读取复杂结构的yml配置项
- vb中如何才能有手型的光标?
- java中的数据结构总结
- 深入理解Solidity 三
- LNMP源码安装脚本
- Oracle优化 -- 关于Database Buffer Cache相关参数DB_CACHE_SIZE的优化设置
- C语言刷抖音源码,iOS多种刷新样式、音乐播放器、仿抖音视频、旅游App等源码...
- Android项目开发—GeoQuiz
- OSPF OVER FR HUB-SPPKE
- DHCP中继原理和配置(含常见配置配置误区)
- 博客营销自动赚钱系统
- 网络基础-应用层:E-mail应用:SMTP协议,POP协议,IMAP协议
- 大一计算机考试题库打字题,大一计算机考试题库
- 如何给PDF文件加密?PDF加密的3种方法
- 04-HTML标签:排版标签
- %2d、%6d(c语言)
- 每日词根——sol(完整可靠安慰,太阳严肃)
- 代码精进之路-读后感
- Openwrt MT7628/MT7620/MT7621——GPIO及LED/KEY的功能实现
- 通过蚂蚁开放联盟链快速上链