C/C++ strict-aliasing
最近发现了一个奇怪的编译参数-fno-strict-aliasing,好奇之下做了一点研究;
重点参考Understanding C/C++ Strict Aliasing;
所谓的aliasing就是多个变量指向同一块内存,变量之间互为别名;
strict-aliasing是一种编译器希望开发者遵守的规则:虽然C/C++变量可以随便赋值(强制类型转换),但也请你们收敛一点,别太天马行空了;
如果开发者按照这个规则写代码了,编译器就可以做更好的代码优化,比如这个例子:
void foo(double *dblptr)
{
anint = ;
*dblptr = ;
bar(anint);
}
如果开发者能够注意不要把int*转成double*,bar(anint)可以直接优化成bar(1);
但没有任何约束不允许这样做,因而编译器不敢做这样的优化,只能在bar(anint)将anint传入bar之前加一条汇编指令再读一下anint的值;
如果开发者确定自己的代码遵守这样的规则了,可以在编译时加一个优化参数-fstrict-aliasing,这个参数在gcc的-O2、-O3、-Os优化级别下都是默认开启的。
然后我对Understanding C/C++ Strict Aliasing文中的两个主要例子做了一下测试:
例子一:
#include <stdio.h> int anint; void bar(int a)
{
printf("%d\n", a);
} void foo(double *dblptr)
{
anint = ;
*dblptr = ;
bar(anint);
} int main()
{
foo((double*)&anint);
return ;
}
编译器版本 | 编译参数 | 结果 |
gcc 4.4.7 | g++ | 0 |
g++ -O3 | 1 | |
g++ -O3 -fno-strict-aliasing | 0 | |
gcc 4.8.5 | g++ | 0 |
g++ -O3 | 1 | |
g++ -O3 -fno-strict-aliasing | 0 | |
gcc 7.3.0 | g++ | 0 |
g++ -O3 | 1 | |
g++ -O3 -fno-strict-aliasing | 0 |
可以看到,这个case被gcc编译器优化坏了,可以用-fno-strict-aliasing规避;
例子二:
#include <iostream>
#include <iomanip> using namespace std; typedef unsigned int uint32_t;
typedef unsigned short uint16_t; uint32_t swaphalves(uint32_t a) {
uint32_t acopy = a;
uint16_t *ptr = (uint16_t*)&acopy;// can't use static_cast<>, not legal.
// you should be warned by that.
uint16_t tmp = ptr[];
ptr[] = ptr[];
ptr[] = tmp;
return acopy;
} int main() {
uint32_t a;
a = ;
cout << hex << setfill('') << setw() << a << endl;
a = swaphalves(a);
cout << setw() << a << endl;
}
编译器版本 | 编译参数 | 结果 |
gcc 4.4.7 | g++ | 00000020 00200000 |
g++ -O3 | ||
gcc 4.8.5 | g++ | 00000020 00200000 |
g++ -O3 | 00000020 00200000 |
|
gcc 7.3.0 | g++ | 00000020 00200000 |
g++ -O3 | 00000020 00200000 |
发现这个case有点意思,只在4.4版本的编译器上会出现问题,高版本编译器上已经修正了。
没有精力再深入研究,就到此为止。
最后再贴上strict aliasing的规则说明,下面这篇文章给出了较好的中文翻译,而且作者显然比我研究的更深入,我就直接抄过来了:
https://blog.csdn.net/dbzhang800/article/details/6720141
- 兼容类型(指相同类型?)或差别仅在于signed、unsigned、const、volatile的类型(比如 const unsigned long *和 long*)
- 聚合类型(struct或class)或联合类型(union)可以alias它们所包含的类型(比如 int 和 包含有int的结构体(包括间接包含))
- 字符类型(char *、signed char*、unsinged char*)可以 alias 任何类型的指针
- [C++] 基类的类型(可能带有const、volatile等cv修饰)可以alias派生类的类型
C/C++ strict-aliasing的更多相关文章
- [翻译]类型双关不好玩:C中使用指针重新解释是坏的
原文地址 Type punning isn't funny: Using pointers to recast in C is bad. C语言中一个重新解释(reinterpret)数据类型的技巧有 ...
- 一个快速double转int的方法(利用magic number)
代码: int i = *reinterpret_cast<int*>(&(d += 6755399441055744.0)); 知识点: 1.reinterpret_cast&l ...
- Python 代码优化常见技巧
代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化.扩展以及文档相关的事情通常需要消耗 80% 的工作量.优化通常包含两方 ...
- [转] Python 代码性能优化技巧
选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...
- Python 代码性能优化技巧
选择了脚本语言就要忍受其速度,这句话在某种程度上说明了 python 作为脚本的一个不足之处,那就是执行效率和性能不够理想,特别是在 performance 较差的机器上,因此有必要进行一定的代码优化 ...
- fstrict-aliasing
承如“optimization blocks”文中所述,由于相同的指针可能指向相关的内存区,因此编译器将不做过分的优化…… 特意搜了下编译器在不同的优化等级下都有哪些默认优化,因此有了此记录(比较长, ...
- 解决部分在Debug模式下程序没问题但是Release模式下出现问题的方法
编译策略介绍 关于优化级别:GCC_OPTIMIZATION_LEVEL 描述如下 None: Do not optimize. [-O0]With this setting, the compil ...
- Linux System Programming 学习笔记(九) 内存管理
1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系 ...
- Linux下编译安装源码包软件 configure ,make, make install, make test/check, make clean
http://www.360doc7.net/wxarticlenew/541275971.html 一.什么是源码包软件? 顾名思义,源码包就是源代码的可见的软件包,基于Linux和BSD系统的软件 ...
随机推荐
- Writing custom protocol for nanomsg
http://vitiy.info/writing-custom-protocol-for-nanomsg/ nanomsg is next version of ZeroMQ lib, provid ...
- kaggle竞赛-保险转化-homesite
时间格式的转化 查看数据类型 查看DataFrame的详细信息 填充缺失值 category 数据类型转化 模型参数设定 结论 该项目是针对kaggle中的homesite进行的算法预测,使用xgbo ...
- D5 F
最近见到了好多跟排列有关的状压dp,好像略微会了一点,用 dp[i][s][j]表示第i位状态为s选择j的方案数,然后递推. 早起大概可以提高人的智商但是会导致人甚至不清,初始化写错了自闭了半个小时 ...
- 微信小程序中显示与隐藏(hidden)
1.wx.wxml页面部分 <view bindtap='click'>点击</view> //这是显示隐藏的部分 <view hidden="{{hidden ...
- Java基础&面向对象(二)
(七)函数 1.数的定义:具有特定功能的一段小程序,也称为方法: 2.函数的特点: 3.函数的应用:结果.是否需要未知内容参与运算: 4.函数的重载:在同一个类中,允许存在一个以上的同名函数,只要它们 ...
- linux --nginx篇
NGINX是什么? nginx是开源的,支持高性能的,高并发的www服务和代理服务软件,就是web服务器,nginx不但是一个优秀的web服务软件,还可以做反向代理,负载均衡,以及缓存服务使用. 优点 ...
- awt
public class MouseTest extends Frame{ private static final long serialVersionUID = 54376853365952763 ...
- 数据格式XML、JSON详解
一. XML数据格式 1.1 XML的定义 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类 ...
- 海思编解码芯片添加64M nor flash
uboot和内核都必须修改. struct spi_info hisfc350_spi_info_table[] : 在结构体里面添加自己的flash节点,我这里用的是MX66LS51235E { & ...
- SpringBoot-性能优化之扫包优化
性能优化 组件自动扫描带来的问题 默认情况下,我们会使用 @SpringBootApplication 注解来自动获取应用的配置信息,但这样也会给应用带来一些副作用.使用这个注解后,会触发自动配置( ...