What is the strict aliasing rule?接受的答案提到您可以使用char *
为其他类型设置别名,但不能使用其他方式。
对我来说没有意义 - 如果我们有两个指针,一个类型char *
而另一个类型struct something *
指向同一个位置,那么第一个别名怎么可能是第二个,但第二个不是第一个别名?
答案 0 :(得分:12)
如果我们有两个指针,一个类型
char *
而另一个类型struct something *
指向同一个位置,那么第一个别名可能是第二个但第二个不是别名第一个?
确实如此,但那不是重点。
关键是如果你有一个或多个struct something
,那么你可以使用char*
来读取它们的组成字节,但是如果你有一个或多个char
s那么你可能不会使用struct something*
来阅读它们。
答案 1 :(得分:10)
参考答案中的措辞略有错误,所以让我们先解决这个问题: 一个对象永远不会混淆另一个对象,但是两个指针可以“别名”同一个对象(意思是,指针指向相同的内存位置 - 正如MM指出的那样,这仍然不是100%正确的措辞,但你得到的想法)。此外,标准本身并不(据我所知)实际上谈论严格的别名,但只提供规则,通过这些规则可以访问或不访问对象。像'-fno-strict-aliasing'这样的编译器标志告诉编译器是否可以假定程序员遵循这些规则(因此它可以根据该假设执行优化)或不执行。
现在回答您的问题:任何对象都可以通过指针访问char
,但char
对象(尤其是char数组)可能无法通过大多数其他指针类型访问。
基于此,编译器可以/必须做出以下假设:
char*
和T*
总是指向同一个对象(彼此别名) - >对称关系。T1
和T2
不是“相关”而不是char
,那么T1*
和T2*
可能永远不会指向同一个对象 - >对称关系char*
可能指向char
或T
对象 T*
可能无法指向char
对象 - > a 对称关系我认为,关于通过指针访问对象的非对称规则背后的主要原理是char
数组可能无法满足例如对齐要求。 int
。
因此,即使没有基于严格别名规则的编译器优化,例如将int
写入地址为0x1,0x2,0x3,0x4的4字节char
数组的位置 - 在最好的情况下 - 会导致性能不佳 - 在最坏的情况下 - 访问a不同的内存位置,因为CPU指令在写入4字节值时可能会忽略最低的两个地址位(所以这里可能会导致写入0x0,0x1,0x2和0x3)。
另请注意,“相关”的含义因语言而异(在C和C ++之间),但这与您的问题无关。
答案 2 :(得分:4)
如果我们有两个指针,一个类型
char *
而另一个类型struct something *
指向同一个位置,那么第一个别名可能是第二个但第二个不是别名第一个?
指针互不别名;这种语言的草率使用。别名是指使用左值访问其他类型的对象。 (取消引用指针给出左值)。
在您的示例中,重要的是对象的类型。举一个具体的例子,让我们说对象是double
。通过解除引用指向double的double
访问char *
是正常的,因为严格的别名规则允许这样做。但是,不允许通过解除引用double
来访问struct something *
(除非,可以说,结构以double
开头!)。
如果编译器正在查看带有char *
和struct something *
的函数,并且它没有可用的有关所指向对象的信息(这实际上不太可能,因为别名传递是在整个计划优化阶段);那么它必须考虑到对象可能实际上是struct something *
的可能性,因此在这个函数中不能进行优化。