“-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. linux中sudoers别名规则

    /etc/sudoers 配置文档中别名规则 别名规则定义格式如下: Alias_Type NAME = item1, item2, ... 或 Alias_Type NAME = item1, it ...

  2. Python 代码优化常见技巧

    代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化.扩展以及文档相关的事情通常需要消耗 80% 的工作量.优化通常包含两方 ...

  3. [转] Python 代码性能优化技巧

    选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...

  4. Python 代码性能优化技巧

    选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...

  5. Yii CModel中rules验证规则[转]

    array( array(‘username’, ‘required’), array(‘username’, ‘length’, ‘min’=>3, ‘max’=>12), array( ...

  6. Theano2.1.14-基础知识之理解为了速度和正确性的内存别名

    来自:http://deeplearning.net/software/theano/tutorial/aliasing.html Understanding Memory Aliasing for ...

  7. Yii CModel中rules验证规则

    array( array(‘username’, ‘required’), array(‘username’, ‘length’, ‘min’=>3, ‘max’=>12), array( ...

  8. ES 10 - Elasticsearch的索引别名和索引模板

    目录 1 索引模板概述 1.1 什么是索引模板 1.2 索引模板中的内容 1.3 索引模板的用途 2 创建索引模板 3 查看索引模板 4 删除索引模板 5 模板的使用建议 5.1 一个index中不能 ...

  9. Item 9: 比起typedef更偏爱别名声明(alias declaration)

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 我确信我们都同意使用STL容器是一个好主意,并且我希望在Item ...

随机推荐

  1. Composer 安装以及使用方法

    Composer 是 PHP 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们. Linux 下安装 curl -sS https://getcomposer.org/ ...

  2. css背景图充满屏幕

    代码: body { /* 加载背景图 */ background: url(resource/inv_bg.png); /* 背景图不平铺 */background-repeat: no-repea ...

  3. sqlite c#

    https://www.cnblogs.com/icebutterfly/p/7850689.html https://www.cnblogs.com/sdadx/p/7127098.html

  4. Could not load file or assembly 'Microsoft.EntityFrameworkCore.Relational

    提示的很明确了,缺少Microsoft.EntityFrameworkCore.Relational引用.nuget安装上即可.

  5. vue2.0一安装的插件详解

    babel-runtime 对ES语法转义 fastclick  移动端300ms兼容 babel-polyfill 兼容Ie浏览器 //babel-polyfill引用 推荐采用webpack入口文 ...

  6. mysql 安装后出现 10061错误

    #服务器端  提示 The vervice already exists! The current server installed #mysqld 服务没有启动 解决办法 移除原来的mysql服务  ...

  7. python subprocess 小例子

    #服务端import socketimport osimport subprocessphone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ...

  8. 免费证书https://lamp.sh/ssl.html

    https(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 http 通道,简单讲是 http 的安全版.即 ht ...

  9. Java中关键字static的使用

    static 关键字 1).static只能修饰成员变量或成员方法,所有非静态是对象相关的,所有静态是类相关的. 2)被static修饰的成员变量成员方法独立于该类的任何对象,它不依赖类的特定的实例, ...

  10. http协议(一)一些基础知识

    当我们在浏览器的地址栏中输入网址,然后点击回车,接着,浏览器就会呈现出我们需要的web界面,那么,这个界面是怎么产生的? web的界面是根据我们输入的URL(网址.地址),浏览器从服务器端获取对应的文 ...