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系统的软件 ...
随机推荐
- 我的海外购页面List
<%@ page language="java" contentType="text/html;charset=UTF-8" %> <%@ t ...
- POI导出复杂的excel;excel公共样式类;excel拼接定制类;数据科学计数法转为普通值
一.excel公共样式类(包含数据科学计数法转为普通值) package com.thinkgem.jeesite.common.utils.excel; import org.apache.poi. ...
- SpringBoot入坑-配置文件使用
经过上一篇的介绍,相信小伙伴们已经按奈不住内心对springboot的向往,本篇我将继续向小伙伴介绍springboot配置文件的配置,已经全局配置参数如何使用,好了下面开始我们今天的内容介绍. 我们 ...
- shell for循环 多个变量
需求:需要输出以下2开头的端口号和其对应的文件 like: port and port_k8s_xxx.conf 其脚本为: #! /bash/shell #以value_name=(value1 v ...
- Go语言基础之数据类型
Go语言基础之数据类型 Go语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串外,还有数组.切片.结构体.函数.map.通道(channel)等.Go 语言的基本类型和其他语言大同小异. ...
- C++常用的文件操作路径函数
shlwapi.dll中的实用API函数发布 在windows system目录下有这个动态链接库 BOOL PathFileExists(LPCTSTR lpszPath)功能:检查文件/路径 ...
- WebH
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...
- A股时间窗口
春节躁动行情:大消费,文娱影视 一号文件:泛农业股 两会行情:两会概念 糖酒会:白酒,糖业 五穷六绝:半年节点,[市场缺钱] 暑期档:文娱影视 国庆行情:军工,文娱影视 年底:阳历年底,[市场缺钱] ...
- A - Shashlik Cooking CodeForces - 1040B
http://codeforces.com/problemset/problem/1040/B Long story short, shashlik is Miroslav's favorite fo ...
- linux之cp和scp的使用
cp 基本介绍 cp主要用于同一台服务器上,目录和文件的复制 表达式 cp [OPTIONS] SOURCE DEST --- 从源路径copy文件到目的路径 常用参数 -a same as -dpR ...