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

时间:2014-05-24 18:08:13

标签: c++ c strict-aliasing

What is the strict aliasing rule?接受的答案提到您可以使用char *为其他类型设置别名,但不能使用其他方式。

对我来说没有意义 - 如果我们有两个指针,一个类型char *而另一个类型struct something *指向同一个位置,那么第一个别名怎么可能是第二个,但第二个不是第一个别名?

3 个答案:

答案 0 :(得分:12)

  

如果我们有两个指针,一个类型char *而另一个类型struct something *指向同一个位置,那么第一个别名可能是第二个但第二个不是别名第一个?

确实如此,但那不是重点。

关键是如果你有一个或多个struct something,那么你可以使用char*来读取它们的组成字节,但是如果你有一个或多个char s那么你可能不会使用struct something*来阅读它们。

答案 1 :(得分:10)

参考答案中的措辞略有错误,所以让我们先解决这个问题: 一个对象永远不会混淆另一个对象,但是两个指针可以“别名”同一个对象(意思是,指针指向相同的内存位置 - 正如MM指出的那样,这仍然不是100%正确的措辞,但你得到的想法)。此外,标准本身并不(据我所知)实际上谈论严格的别名,但只提供规则,通过这些规则可以访问或不访问对象。像'-fno-strict-aliasing'这样的编译器标志告诉编译器是否可以假定程序员遵循这些规则(因此它可以根据该假设执行优化)或不执行。

现在回答您的问题:任何对象都可以通过指针访问char,但char 对象(尤其是char数组)可能无法通过大多数其他指针类型访问。 基于此,编译器可以/必须做出以下假设:

  1. 如果实际对象本身的类型未知,char*T*总是指向同一个对象(彼此别名) - >对称关系。
  2. 如果T1T2不是“相关”而不是char,那么T1*T2*可能永远不会指向同一个对象 - >对称关系
  3. char*可能指向charT 对象
  4. T*可能无法指向char 对象 - > a 对称关系
  5. 我认为,关于通过指针访问对象非对称规则背后的主要原理是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 *的可能性,因此在这个函数中不能进行优化。