5 回答
TA贡献1773条经验 获得超3个赞
这是严格的别名规则,可以在C ++ 03标准的3.10节中找到(其他答案提供了很好的解释,但没有提供规则本身):
如果程序试图通过不同于以下类型之一的左值访问对象的存储值,则行为未定义:
对象的动态类型,
一个cv限定版本的动态类型的对象,
与对象的动态类型对应的有符号或无符号类型的类型,
一种类型,是有符号或无符号类型,对应于对象动态类型的cv限定版本,
一种聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),
一个类型,它是对象动态类型的(可能是cv限定的)基类类型,
a
char
或unsigned char
类型。
C ++ 11和C ++ 14措辞(强调变化):
如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:
对象的动态类型,
一个cv限定版本的动态类型的对象,
与对象的动态类型类似的类型(如4.4中所定义),
与对象的动态类型对应的有符号或无符号类型的类型,
一种类型,是有符号或无符号类型,对应于对象动态类型的cv限定版本,
聚合或联合类型,包括其元素或非静态数据成员中的上述类型之一(递归地,包括子聚合或包含联合的元素或非静态数据成员),
一个类型,它是对象动态类型的(可能是cv限定的)基类类型,
a
char
或unsigned char
类型。
两个变化很小:glvalue而不是lvalue,以及聚合/联合案例的澄清。
第三个变化提供了更强有力的保证(放宽强混叠规则):类似类型的新概念现在可以安全别名。
另外,Ç措词(C99; ISO / IEC 9899:1999 6.5 / 7;完全相同的措词在ISO / IEC 9899中使用:2011§6.5¶7):
对象的存储值只能由具有以下类型之一(73)或88)的左值表达式访问:
与对象的有效类型兼容的类型,
与对象的有效类型兼容的类型的限定版本,
与对象的有效类型对应的有符号或无符号类型的类型,
与有效类型的对象的限定版本对应的有符号或无符号类型的类型,
聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或者
一个字符类型。
73)或88)此列表的目的是指定对象可能或可能不具有别名的情况。
TA贡献1946条经验 获得超4个赞
作为Doug T.已经写过的补充,这里有一个简单的测试用例,可能用gcc触发它:
check.c
#include <stdio.h>void check(short *h,long *k){ *h=5; *k=6; if (*h == 5) printf("strict aliasing problem\n");}int main(void){ long k[1]; check((short *)k,k); return 0;}
编译gcc -O2 -o check check.c
。通常(我尝试过的大多数gcc版本)都输出“严格别名问题”,因为编译器假定“h”不能与“check”函数中的“k”相同。因此,编译器优化了if (*h == 5)
远离并始终调用printf。
对于那些感兴趣的人是x64汇编程序代码,由gcc 4.6.3生成,在ubuntu 12.04.2 for x64上运行:
movw $5, (%rdi)movq $6, (%rsi)movl $.LC0, %edi jmp puts
所以if条件完全从汇编代码中消失了。
- 5 回答
- 0 关注
- 870 浏览
添加回答
举报