“-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”及类型双关相关推荐

  1. Understanding C/C++ Strict Aliasing

    Understanding C/C++ Strict Aliasing 深入理解C/C++中的`Strict Aliasin`规则 or - Why won't the #$@##@^% compil ...

  2. 严格的别名规则是什么?

    当询问C中常见的未定义行为时 ,人们有时会参考严格的别名规则. 他们在说什么? #1楼 正如Doug T.已经写过的附录一样,这是一个简单的测试用例,可能会用gcc触发它: 检查 #include & ...

  3. GCC strict aliasing – 嫉妒就是承认自己不如别人

    GCC strict aliasing – 嫉妒就是承认自己不如别人 GCC strict aliasing 事情是这样的.我们对tair(淘宝的分布式Key/Value系统)动了一次大手术,更换了网 ...

  4. strict aliasing

    strict aliasing一文中将这些条文允许alias总结如下: 1.兼容类型(指相同类型?)或差别仅在于signed.unsigned.const.volatile的类型(比如 const u ...

  5. C/C++ Strict Alias 小记

    什么是Aliasing? 理解strict aliasing一文中这样描述: 当两个指针指向同一块区域或对象时,我们称一个指针 alias 另一个指针. strict aliasing一文中这样描述: ...

  6. Android 存档

    Android 存档 用Eclipse开发与调试纯粹的Android C++程序,非ndk-build.ndk-gdb 2011 年 09 月 01 日 分类目录 :Android 2 本文欢迎转载, ...

  7. strict alias 的含义

    Alias 的定义 一个指针叫做另一个指针的 alias (别名)如果这两个指针都指向相同的地址或对象. 在C99标准里,建立一个与原类型不同的别名是非法的.这叫做 strict aliasing 规 ...

  8. ESLint里的规则教会我,无规矩 不编程

    编程风格要统一 编程风格这个东西,说实在的对于刚加入团队的新成员来说还是很难让人完全适应的.因为每人的编程风格都不同,完全是各有千秋的既视感啊 到了新公司后团队中的每个人也都有各自一套的编程习惯,撸起 ...

  9. Go 学习笔记(32)— 类型系统(命名类型、未命名类型、底层类型、类型强制转换、类型别名和新声明类型)

    1. 命名类型和未命名类型 1.1 命名类型 类型可以通过标识符来表示,这种类型称为命名类型( Named Type ). Go 语言的基本类型中有 20 个预声明简单类型都是命名类型, Go 语言还 ...

最新文章

  1. python的数字转汉字金额的不完善代码
  2. 修改用户和用户组权限
  3. Oracle官方推荐的性能测试工具!简单、精准又直观!
  4. python如何关闭multiprocess_python 开启进程两种方法 multiprocessing模块 介绍
  5. 使用CommandLineRunner或ApplicationRunner接口创建bean
  6. 我死了,你会娶别的女人吗?
  7. LeetCode-69 x的平方根
  8. 如何学习32位单片机
  9. 外贸必备——各国常用搜索引擎
  10. <数据结构> 顺序表
  11. 第三章:用python实现常用的用户分层模型(RFM模型)
  12. 1.计算机网络的发展,计算机网络的发展史「简述」
  13. 将姓名转为拼音,首字母大写
  14. 【论文阅读】Slot-Gated Modeling for Joint Slot Filling and Intent Prediction
  15. dis的前缀单词有哪些_前缀dis包含哪两种含义
  16. DSP F28335时钟及控制系统
  17. C语言学习笔记(3)函数
  18. ubantu系统从命令行进入桌面
  19. AdvanCell完成由晨兴创投领投的1,800万澳元B轮融资
  20. Codevs 6个朋友

热门文章

  1. UEFI Drivers UEFI Driver Model
  2. 连不上微软服务器 dns,无法联系主 DNS 服务器 | Microsoft Docs
  3. VMware 虚拟机演示进入U盘PE系统
  4. 服务器装系统进pe界面就死机了,电脑可以进入PE系统,但重装就是重启,装不了系统是什么原因?...
  5. e1000网卡和DMA
  6. Jenkins Gitlab 插件及 Gitlab 全局变量
  7. 英特尔AVX指令集解析
  8. 什么是堡垒机?堡垒机有何优势?
  9. 卡普公司鸿蒙手机,每人日接受信息量相当于看174份报纸
  10. java poi 添加列数据_java使用POI将数据导出放入Excel