什么是Aliasing?

理解strict aliasing一文中这样描述:

  • 当两个指针指向同一块区域或对象时,我们称一个指针 alias 另一个指针。

strict aliasing一文中这样描述:

  • Aliasing 是指多于一个的左值指向同一块区域。

比如:

int i;
int *pi = &i;

pi alias i

 

int i;
void foo(int &i1, int &i2){}
foo(i,i);

i1 alias i2

 

int i;
float *pf = (float*)&i;
*pf = 0;

pf alias i

违反strict alias ?

什么是Strict Aliasing?

按照 理解strict aliasing 一文描述:

  • Strict aliasing 是C或C++编译器的一种假设:不同类型的指针绝对不会指向同一块内存区域。

例子

暂且不管这句话,我们看个例子:

  • hello.c
#include <stdio.h>

int a;
int f(float *b)
{
    a = 1;
    *b = 0;
    return a;
}

int main()
{
    printf("%d\n", f((float*)&a));
    return 0;
}

用GCC4.4 加 -O3 编译(GCC4.5似乎看不到这个效果,fixme):

debao@ubuntu:~/ttt$ gcc-4.4 -Wall -O3 hello.c
hello.c: In function ‘main’:
hello.c:7: warning: dereferencing pointer ‘a.16’ does break strict-aliasing rules
hello.c:13: note: initialized from here

运行程序,结果为 1

debao@ubuntu:~/ttt$ ./a.out
1

而如果不加 -O3,程序结果为 0

debao@ubuntu:~/ttt$ gcc-4.4 -Wall  hello.c
debao@ubuntu:~/ttt$ ./a.out
0

原因

警告信息说:对指针a.16的解引用打破了 strict-aliasing 规则。

int a;
int f(float *b)
{
    a = 1;
    *b = 0;
    return a;
}

按照strict aliasing规则,编译器认为 a 和 *b 绝不会指向同一块存储区域,故而优化后返回a时直接返回了1。

那么哪些 alias 是不会破坏规则的呢?或者说规则在哪儿呢?

允许的alias

C/C++ 中相应的标准原文见下一节。strict aliasing一文中将这些条文可以总结如下:

  • 兼容类型(指相同类型?)或差别仅在于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派生类的类型

为什么要strict alias?

主要目的应该就是为了使编译器能生成更高效的代码。

考虑下面的代码:

int a;
void f( double * b )
{
a = 1;
*b = 2.0;
g(a);
}

如果没有strict alias假定,编译器必须始终假设b可能会指向a所在的地址,从而不能将g(a)调用优化成g(1)

strict alias规则中,为什么允许char类型可以alias任何对象呢?

  • Character pointer types are often used in the bytewise manipulation of objects;a byte stored through such a character pointer may well end up in an object of any type.

为什么class、struct、union可以 alias 它们包含的对象类型呢?

  • Structure and union types also have problematic aliasing properties:

     struct fi{ float f; int i;};
    void f( struct fi * fip, int * ip )
    {
    ...

乱七八糟

这可能是一个很常用的东西:比如一个union fi{float f;int i;}对象,我们可以用f成员保存一个浮点数进去,用i成员读一个整数出来。这在C99以及C1X标准中都是明文允许的。

  • If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

可是,在C++标准中却没有类似的条文,尽管C++编译器几乎都支持这种用法,可能这个在C++中仍属于未定义行为。

C/C++标准条文

  • C89 (6.3,我没找到C89的标准原文,对此不确定)
  • C99 (6.5/7)
  • C++98 (3.10/15)
  • C++0x (3.10/10)

都有如下的表述:如果使用不符合下表中条文所列类型的 alias 来访问一个对象,其行为是为定义的!!!

  • If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined
 

条文

标准

1

the dynamic type of the object,

C++0x, C++98

a type compatible with the effective type of the object,

C99

2

a cv-qualified version of the dynamic type of the object,

C++0x, C++98

a type similar to the dynamic type of the object,

C++0x,

a qualified version of a type compatible with the effective type of the object,

C99

3

a type that is the signed or unsigned type corresponding to the dynamic type of the object,

C++0x, C++98

a type that is the signed or unsigned type corresponding to the effective type of the object,

C99

4

a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,

C++0x, C++98

a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

C99

5

an aggregate or union type that includes one of the aforementioned types among its elements or nonstatic data members (including, recursively, an element or non-static data member of a subaggregate or contained union),

C++0x, C++98

an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

C99

6

a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,

C++0x, C++98

7

a char or unsigned char type.

C++0x, C++98

a character type.

C99

参考

  • http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

  • http://en.wikipedia.org/wiki/Aliasing_%28computing%29

  • http://en.wikipedia.org/wiki/Type_punning

  • http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule

  • http://dbp-consulting.com/tutorials/StrictAliasing.html

C/C++ Strict Alias 小记相关推荐

  1. strict alias 的含义

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

  2. 脚手架架构设计和框架搭建 - 框架搭建

    目录 Lerna简介 原生脚手架开发痛点分析 Lerna简介 优势 官网 Lerna 开发脚手架流程(划重点) 基于 Lerna 搭建脚手架框架 Lerna 核心操作 Lerna 发布流程 Lerna ...

  3. ffmpeg录屏/摄像头/指定窗口;别名alias设置

    关于ffmpeg的使用方法很多,我简单写一下今天我捣鼓的几个.因为我的项目中要用到录屏和录制摄像头,所以试了下.网上关于录制指定窗口的方法并不多,我也是找了好久,试了好久才试出来的. 好了,废话不多说 ...

  4. strict aliasing

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

  5. svn update命令小记

    2019独角兽企业重金招聘Python工程师标准>>> svn update命令小记 今天在使用svn update命令的时候,出现了这么一个提示: ATTENTION! Your ...

  6. JavaScript严格模式 use strict

    1.在严格模式下,变量必须显示声明(var/let/const),直接给变量赋值,不会隐式创建全局变量 (function(){//非严格模式a = 10;console.log(a); //10 } ...

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

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

  8. Understanding C/C++ Strict Aliasing

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

  9. Beatles小记-分布式数据流分析框架(一)

    Author:放翁(文初) Email:fangweng@taobao.com Mblog:weibo.com/fangweng Blog: http://blog.csdn.net/cenwench ...

最新文章

  1. python基础语言与应用第五章_《Python基础教程》 读书笔记 第五章(下)循环语句...
  2. Qt中的QDialog
  3. 开源版本_开源版本PowerShell Core 6.2 发布
  4. Tarjan算法学习1-双连通
  5. Netty之Channel的继承关系
  6. C语言:L1-037 A除以B (10分)(解题报告)
  7. java在线教程_如何自学java-已拿阿里25k offer
  8. flink的savepoint实验-java
  9. 前端学习(2674):vue3修改
  10. windows批量关机
  11. MAGENTO与性能优化
  12. 超融合架构与传统IT架构的区别
  13. 【关于如何调用java的private成员变量】
  14. Git创建版本库及git init 、add 和 commit -m 的基本使用
  15. 【技美百人计划】屏幕空间实现dither等溶解效果
  16. 【系统收藏——中天证券创鑫软件 官方版 [同时支持三板、港股行情、沪深300指数。]】
  17. 怎样在左边增加中国农历?
  18. 内网异地备份_服务器数据全自动异地备份解决方案
  19. APP 对接 java 微信支付统一下单接口
  20. Maven打包SpringBoot项目镜像并推送至私有Harbor仓库

热门文章

  1. 云南农业大学C语言程序设计,云南农业大学341农业知识综合三考研真题笔记期末题等...
  2. 《炬丰科技-半导体工艺》硅片清洗技术的演变
  3. java中table属性,Table边框使用方法及属性大全
  4. Android 入门项目NoteBook
  5. android.support.v7.app 包下载,“package android.support.v7.app does not exist” error in androidStudio...
  6. 雷达图 和 K线图(蜡烛图),OHLC线图
  7. 山大计算机专业就业前景如何,山东大学53个就业率高达100%的专业,有冷门也有热门...
  8. 常见测试函数图像及求解方法(一至四)
  9. 通过JS动态设置meta标签,根据手机屏幕分辨率自动缩放适配各手机(包括适配华为、oppo大屏幕手机、钉钉、微信)
  10. 模电知识点总结(四) 晶体二极管的应用