以下代码是否违反严格的别名?

时间:2019-01-19 15:45:51

标签: c strict-aliasing

以下代码是否违反严格的别名?

int a = 0;
*((int *)((char *)&a)) = 1;

为什么不呢?,因为我们最终使用合法的a来引用int int *的指针

为什么?,因为我们将char *强制转换为int *并取消引用(int *),这似乎是严格的别名冲突

3 个答案:

答案 0 :(得分:2)

严格的别名规则不关心中间类型转换。他们只关心最终用于访问对象的指针的类型,以及对象本身的原始类型(从技术上讲,它是“有效类型”,但现在并不重要)。

在示例代码中,您使用的地址是int。结果的类型为int *。您将该指针转换为char *,然后再次将其转换为int *,然后才取消引用它。访问中使用的指针类型为int *,指向的对象类型为int,因此严格的别名规则没有问题。

您是正确的,严格的别名规则相对于char是不对称的,但这仅在对象本身的类型为char或访问中使用的指针的类型时才重要是char

char x[sizeof(int)] = { 0 };
*(int *)x = 1;  // undefined behavior

int y = 1234;
*(char *)y = 0; // valid; value of y becomes unspecified

从理论上讲,两种指针类型之间的强制转换会丢失信息,但从其他类型强制转换为char *并再次返回时不会丢失信息。此外,这仅与您现在不太可能遇到的计算机有关。我真的不记得一个例子。

答案 1 :(得分:1)

此代码有效。允许在两种对象指针类型之间进行转换,前提是没有对齐问题,并且可以明确地转换为char *以访问对象表示形式(即读取单个字节)。

C standard的第6.3.2.3p7节指出:

  

指向对象类型的指针可能会转换为指向对象类型的指针   不同的对象类型。如果结果指针不正确   如果为引用的类型对齐,则行为未定义。   否则,当再次转换回时,结果应进行比较   等于原始指针。当指向对象的指针是   转换为指向字符类型的指针,结果指向   对象的最低寻址字节。的连续增量   结果,根据对象的大小,产生指向其余对象的指针   对象的字节数。

由于您是从int *char *,然后又回到int *,所以这里没有严格的别名冲突。

答案 2 :(得分:1)

不,这不是违规。

  

因为我们将char *投射到int *

您遗漏了您提到的char *实际上是int *的那部分。因此,最终通过指向int的指针来访问int类型-这是完全有效的。