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