严格的别名规则和'char *'指针

什么是严格的锯齿规则被接受的答案? 提到你可以使用char *来别名,而不是别的方式。

对我来说没有任何意义 – 如果我们有两个指针,一个是char *types,另一个是struct something *指向同一个位置,那么第二个别名可能是第二个别名,而第二个别名首先?

所引用的答案中的措辞有些错误,所以让我们先解决它:一个对象不会混淆另一个对象 ,但是两个指针可以“混淆”同一个对象(也就是说,指针指向相同的内存位置 – 就像MM指向的那样出来,这仍然不是100%正确的措辞,但你得到的想法)。 而且,标准本身并不是(据我所知)实际上根本就谈论严格的别名,而只是给出规则,通过哪种expression式可以访问一个对象。 像“-fno-strict-aliasing”这样的编译器标志告诉编译器它是否可以假定程序员遵循这些规则(所以它可以根据这个假设来执行优化)。

现在你的问题:任何对象都可以通过指向 char指针来访问,但char 对象 (尤其是char数组)可能不能通过大多数其他指针types来访问。 基于此,编译器可以/必须做出以下假设:

  1. 如果实际对象本身的types未知,则char*T*总是可以指向同一个对象(别名) – >对称关系。
  2. 如果T1T2不是“相关”而不是char ,那么T1*T2*可能永远不会指向同一个对象 – >对称关系
  3. char*可能指向charT 对象
  4. 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 *的可能性,所以在这个函数内部不能进行优化。