严格别名规则“-fstrict-aliasing”和“-fno-strict-aliasing”及类型双关
“-fstrict-aliasing”表示启用严格别名规则,“-fno-strict-aliasing”表示禁用严格别名规则,当gcc的编译优化参数为“-O2”、“-O3”和“-Os”时,默认会打开“-fstrict-aliasing”。
什么是严格别名规则?gcc对严格别名的定义:
|
In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. 即,编译器假定相同的内存地址绝不会存放不同类型的数据,否则即破坏了严格别名规则。 |
别名的定义可理解为:同一内存地址有不同的名称,比如:
|
int m = 0x20190101; int* p1 = &m; int *p2 = &m; int *p3 = p2; int n = m; |
这里“&m”、“p1”、“p2”和“p3”均是同一内存地址的别名,但n不是,因此涉及严格别名,是和指针相关的。
下列代码,如果使用“-O2”、“-O3”或“-Os”编译,并且加不“-fno-strict-aliasing”,则“*s”的结果是未定义的,不同的编译器可能产生不同的结果,即使同一编译器也可能运行时结果不尽相同:
|
#include <stdio.h> int main() { int m = 0x12345678; short* s = (short*)&m; // 使用C++的方式也不可:short* s = reinterpret_cast<short*>(&m); printf("%x\n", *s); return 0; } |
gcc-4.1.2上运行情况,可以看到每次结果都不相同:
|
> g++ --version > g++ -g -o e e.cpp -O2 > ./e 6590 > ./e 590 > ./e ffffb590 |
怎么解决严格别名问题?采用类型相关(type-punning),手段是采用联合体union,比如下面这种类型相关的用法是安全的:
|
#include <stdio.h> union X { int m; short s; }; int main() { X x; x.m = 0x12345678; short s = x.s; printf("%x\n", s); return 0; } |
然而,下列用法仍然是不安全的(多版本gcc实测正常,也未有“dereferencing type-punned pointer will break strict-aliasing rules”编译告警,但gcc手册指出结果可能不符合预期):
|
#include <stdio.h> union X { int m; short s; }; int main() { X x; x.m = 0x12345678; short* s = &x.s; printf("%x\n", *s); return 0; } |
下列代码的结果也是未定义的(多版本gcc实测也正常,同样未有编译告警,但gcc手册指出结果是未定义的):
|
#include <stdio.h> union X { int m; short s; }; int main() { int m = 0x12345678; short s = ((X*)&m)->s; printf("%x\n", s); return 0; } |
如果担心风险,可加上编译参数“-fno-strict-aliasing”,但这会阻止gcc相关的优化。不过下列别名总是安全的:
1) “unsigned int”别名“int”,其它类似
2) “char”别名其它任何类型
严格别名规则“-fstrict-aliasing”和“-fno-strict-aliasing”及类型双关的更多相关文章
- linux中sudoers别名规则
/etc/sudoers 配置文档中别名规则 别名规则定义格式如下: Alias_Type NAME = item1, item2, ... 或 Alias_Type NAME = item1, it ...
- Python 代码优化常见技巧
代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化.扩展以及文档相关的事情通常需要消耗 80% 的工作量.优化通常包含两方 ...
- [转] Python 代码性能优化技巧
选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...
- Python 代码性能优化技巧
选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...
- Yii CModel中rules验证规则[转]
array( array(‘username’, ‘required’), array(‘username’, ‘length’, ‘min’=>3, ‘max’=>12), array( ...
- Theano2.1.14-基础知识之理解为了速度和正确性的内存别名
来自:http://deeplearning.net/software/theano/tutorial/aliasing.html Understanding Memory Aliasing for ...
- Yii CModel中rules验证规则
array( array(‘username’, ‘required’), array(‘username’, ‘length’, ‘min’=>3, ‘max’=>12), array( ...
- ES 10 - Elasticsearch的索引别名和索引模板
目录 1 索引模板概述 1.1 什么是索引模板 1.2 索引模板中的内容 1.3 索引模板的用途 2 创建索引模板 3 查看索引模板 4 删除索引模板 5 模板的使用建议 5.1 一个index中不能 ...
- Item 9: 比起typedef更偏爱别名声明(alias declaration)
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 我确信我们都同意使用STL容器是一个好主意,并且我希望在Item ...
随机推荐
- 微信小程序中用setData修改一个对象的属性值
原创文章 1. Page({ data: { items:{ //items为一个对象,is_like和like分别为其两个属性 is_like: 0, like: 0 ...
- java String 中替换"\"为"\\"
表示路径的字符串 c:\work\test\afd.out, 要形成 c:\\work\\test\\afd.out 用 String str = strBsf.replaceAll(" ...
- make ;makefile; cmake; qmake的区分
1. make 是用来执行Makefile的.2. Makefile是类unix环境下(比如Linux)的类似于批处理的"脚本"文件.其基本语法是: 目标+依赖+命令,只有在目标文 ...
- samrty模板变量操作符
count_sentences [计算句数],示例:{$smarty.get.name|count_sentences} count_words [计算词数],示例:{$smarty.get.name ...
- 使用swoole编写简单的echo服务器
server.php代码如下: <?php class EchoServer { protected $serv = null; public function __construct() { ...
- Linux执行命令时遇到的些问题
1.执行lsb_release -a,提示 未安装lsb_release导致的,执行一下yum install redhat-lsb -y,问题解决 2.配置tomcat站点后重启tomcat,提示找 ...
- ofo退押金脚本
同事钉钉给的 因为押金一直没退,电话很难打进去,咨询客服排队要等好久,一直几千位. 长时间挂机就自动退出客服了,所以自动写了一个脚本,目前已经成功退押金了.所以共享出来 1.关注ofo小黄车订阅号,注 ...
- PAT 1043 输出PATest(20)(代码+思路)
1043 输出PATest(20)(20 分) 给定一个长度不超过10000的.仅由英文字母构成的字符串.请将字符重新调整顺序,按"PATestPATest...."这样的顺序输出 ...
- tableView中cell的复用机制
TableView的重用机制,为了做到显示和数据分离,IOS tableView的实现并且不是为每个数据项创建一个tableCell.而是只创建屏幕可显示最大个数的cell,然后重复使用这些cell, ...
- 判断and ,or
and 和 or 是条件 与和或,记住一条,and 是两边同时都满足,or 是只有满足一个条件就成立. # print(1 or False) #条件1成立,条件2不成立.打印条件1 #返回: 1# ...