什么是严格别名规则?

当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明。
他们在说什么?

四季花海
浏览 818回答 5
5回答

小怪兽爱吃肉

我发现的最佳解释是Mike Acton,了解严格别名。它主要关注PS3开发,但这基本上只是GCC。来自文章:“严格别名是由C(或C ++)编译器做出的一个假设,即取消引用指向不同类型对象的指针永远不会引用相同的内存位置(即彼此别名)。”所以基本上如果你有一个int*指向包含一个内存的内存int然后你指向一个float*内存并将其用作float你打破规则。如果您的代码不遵守这一点,那么编译器的优化器很可能会破坏您的代码。规则的例外是a char*,允许指向任何类型。

慕容3067478

这是严格的别名规则,可以在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)此列表的目的是指定对象可能或可能不具有别名的情况。

拉风的咖菲猫

严格的别名不仅仅指向指针,它也会影响引用,我为boost开发人员wiki写了一篇关于它的文章,并且它很受欢迎,我把它变成了我咨询网站上的一个页面。它完全解释了它是什么,为什么它如此混淆了人们以及如何处理它。严格别名白皮书。特别是它解释了为什么工会是C ++的危险行为,以及为什么使用memcpy是C和C ++中唯一可移植的解决方案。希望这是有帮助的。

绝地无双

作为Doug T.已经写过的补充,这里有一个简单的测试用例,可能用gcc触发它:check.c#include&nbsp;<stdio.h>void&nbsp;check(short&nbsp;*h,long&nbsp;*k){ &nbsp;&nbsp;&nbsp;&nbsp;*h=5; &nbsp;&nbsp;&nbsp;&nbsp;*k=6; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(*h&nbsp;==&nbsp;5) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("strict&nbsp;aliasing&nbsp;problem\n");}int&nbsp;main(void){ &nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k[1]; &nbsp;&nbsp;&nbsp;&nbsp;check((short&nbsp;*)k,k); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;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&nbsp;&nbsp;&nbsp;&nbsp;$5,&nbsp;(%rdi)movq&nbsp;&nbsp;&nbsp;&nbsp;$6,&nbsp;(%rsi)movl&nbsp;&nbsp;&nbsp;&nbsp;$.LC0,&nbsp;%edi jmp&nbsp;puts所以if条件完全从汇编代码中消失了。
打开App,查看更多内容
随时随地看视频慕课网APP