最近发现了一个奇怪的编译参数-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的更多相关文章

  1. [翻译]类型双关不好玩:C中使用指针重新解释是坏的

    原文地址 Type punning isn't funny: Using pointers to recast in C is bad. C语言中一个重新解释(reinterpret)数据类型的技巧有 ...

  2. 一个快速double转int的方法(利用magic number)

    代码: int i = *reinterpret_cast<int*>(&(d += 6755399441055744.0)); 知识点: 1.reinterpret_cast&l ...

  3. Python 代码优化常见技巧

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

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

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

  5. Python 代码性能优化技巧

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

  6. fstrict-aliasing

    承如“optimization blocks”文中所述,由于相同的指针可能指向相关的内存区,因此编译器将不做过分的优化…… 特意搜了下编译器在不同的优化等级下都有哪些默认优化,因此有了此记录(比较长, ...

  7. 解决部分在Debug模式下程序没问题但是Release模式下出现问题的方法

    编译策略介绍 关于优化级别:GCC_OPTIMIZATION_LEVEL 描述如下 None: Do not optimize.  [-O0]With this setting, the compil ...

  8. Linux System Programming 学习笔记(九) 内存管理

    1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系 ...

  9. Linux下编译安装源码包软件 configure ,make, make install, make test/check, make clean

    http://www.360doc7.net/wxarticlenew/541275971.html 一.什么是源码包软件? 顾名思义,源码包就是源代码的可见的软件包,基于Linux和BSD系统的软件 ...

随机推荐

  1. Inside The C++ Object Model(三)

    ============================================================================3-0. 类所占的内存大小受到三个因素的影响:( ...

  2. 从0移植uboot(五) _实现串口输出

    串口作为一种非常简单的通信方式,才是嵌入式系统调试的王道,通过设置串口输出,我们可以将程序运行的情况直接通过串口线输出到屏幕上,对于这种异常重要的功能,uboot原生就提供了支持,但为此我们需要做一些 ...

  3. 将VSCode添加到右键

    https://www.cnblogs.com/Rexcnblog/p/8046371.html https://www.jianshu.com/p/b49002fa10a7 @echo Off :S ...

  4. centos 7 mysql 开启binlog

    一.前言 本文章用到的mysql 为5.7版本. 按照https://blog.csdn.net/king_kgh/article/details/74800513中的步骤操作,结果启动失败. 配置文 ...

  5. iOS WebView中视频横屏播放返回导航栏在状态栏下面

    iOS9以上系统横屏播放UIWebView中的视频返回后会出现以下问题:1.如图,UIWebView中包含一个视频:   1 2.播放web内容中的视频,并横屏观看:   2 3.直接在横屏状态下返回 ...

  6. 关于Redis 应用 的一些 感悟

    最近在项目中 使用了 Redis技术

  7. 矩阵取数问题(dp,高精)

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n×mn \times mn×m的矩阵,矩阵中的每个元素ai,ja_{i,j}ai,j​均为非负整数.游戏规则如下: 每次取数时须从每行各取走 ...

  8. juqery 点击分页显示,指定一页显示多少个,首次加载显示多少个

    源代码html: //源代码:html <div class="jq22"> <div class="hidden"> <li&g ...

  9. 图解android开发在界面上显示图片

    图解android开发在界面上显示图片<申明:转自百度> <原文章地址:http://jingyan.baidu.com/article/49711c6153a277fa441b7c ...

  10. 怎么将APE转MP3,APE转MP3的方法

    怎样实现APE转MP3的问题呢?很多时候我们从网上所下载的音乐格式,可能并不是我们所需要的音乐格式.如APE音乐格式,那么当我们下载了自己并不需要的APE音乐格式我们应该如何将其转换为自己需要的MP3 ...