严格别名规则“-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”及类型双关相关推荐
- Understanding C/C++ Strict Aliasing
Understanding C/C++ Strict Aliasing 深入理解C/C++中的`Strict Aliasin`规则 or - Why won't the #$@##@^% compil ...
- 严格的别名规则是什么?
当询问C中常见的未定义行为时 ,人们有时会参考严格的别名规则. 他们在说什么? #1楼 正如Doug T.已经写过的附录一样,这是一个简单的测试用例,可能会用gcc触发它: 检查 #include & ...
- GCC strict aliasing – 嫉妒就是承认自己不如别人
GCC strict aliasing – 嫉妒就是承认自己不如别人 GCC strict aliasing 事情是这样的.我们对tair(淘宝的分布式Key/Value系统)动了一次大手术,更换了网 ...
- strict aliasing
strict aliasing一文中将这些条文允许alias总结如下: 1.兼容类型(指相同类型?)或差别仅在于signed.unsigned.const.volatile的类型(比如 const u ...
- C/C++ Strict Alias 小记
什么是Aliasing? 理解strict aliasing一文中这样描述: 当两个指针指向同一块区域或对象时,我们称一个指针 alias 另一个指针. strict aliasing一文中这样描述: ...
- Android 存档
Android 存档 用Eclipse开发与调试纯粹的Android C++程序,非ndk-build.ndk-gdb 2011 年 09 月 01 日 分类目录 :Android 2 本文欢迎转载, ...
- strict alias 的含义
Alias 的定义 一个指针叫做另一个指针的 alias (别名)如果这两个指针都指向相同的地址或对象. 在C99标准里,建立一个与原类型不同的别名是非法的.这叫做 strict aliasing 规 ...
- ESLint里的规则教会我,无规矩 不编程
编程风格要统一 编程风格这个东西,说实在的对于刚加入团队的新成员来说还是很难让人完全适应的.因为每人的编程风格都不同,完全是各有千秋的既视感啊 到了新公司后团队中的每个人也都有各自一套的编程习惯,撸起 ...
- Go 学习笔记(32)— 类型系统(命名类型、未命名类型、底层类型、类型强制转换、类型别名和新声明类型)
1. 命名类型和未命名类型 1.1 命名类型 类型可以通过标识符来表示,这种类型称为命名类型( Named Type ). Go 语言的基本类型中有 20 个预声明简单类型都是命名类型, Go 语言还 ...
最新文章
- python的数字转汉字金额的不完善代码
- 修改用户和用户组权限
- Oracle官方推荐的性能测试工具!简单、精准又直观!
- python如何关闭multiprocess_python 开启进程两种方法 multiprocessing模块 介绍
- 使用CommandLineRunner或ApplicationRunner接口创建bean
- 我死了,你会娶别的女人吗?
- LeetCode-69 x的平方根
- 如何学习32位单片机
- 外贸必备——各国常用搜索引擎
- <数据结构> 顺序表
- 第三章:用python实现常用的用户分层模型(RFM模型)
- 1.计算机网络的发展,计算机网络的发展史「简述」
- 将姓名转为拼音,首字母大写
- 【论文阅读】Slot-Gated Modeling for Joint Slot Filling and Intent Prediction
- dis的前缀单词有哪些_前缀dis包含哪两种含义
- DSP F28335时钟及控制系统
- C语言学习笔记(3)函数
- ubantu系统从命令行进入桌面
- AdvanCell完成由晨兴创投领投的1,800万澳元B轮融资
- Codevs 6个朋友
热门文章
- UEFI Drivers UEFI Driver Model
- 连不上微软服务器 dns,无法联系主 DNS 服务器 | Microsoft Docs
- VMware 虚拟机演示进入U盘PE系统
- 服务器装系统进pe界面就死机了,电脑可以进入PE系统,但重装就是重启,装不了系统是什么原因?...
- e1000网卡和DMA
- Jenkins Gitlab 插件及 Gitlab 全局变量
- 英特尔AVX指令集解析
- 什么是堡垒机?堡垒机有何优势?
- 卡普公司鸿蒙手机,每人日接受信息量相当于看174份报纸
- java poi 添加列数据_java使用POI将数据导出放入Excel