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

Does the following code violate strict aliasing?

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

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

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

为什么是? 因为我们将 char * 转换为 int * 并取消引用它(int *),这似乎是一个严格的别名违规

此代码有效。如果没有对齐问题,允许在两个对象指针类型之间转换并返回,并且明确允许转换为 char * 以访问对象表示(即读取单个字节)。

C standard 的第 6.3.2.3p7 节指出:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

由于您从 int * 转换为 char * 然后返回 int *,因此这里没有严格的别名违规。

不,这不是违规。

because we cast the char * to int *

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

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

在您的示例代码中,您获取了 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 * 并再次返回时不会。此外,这仅与您现在不太可能遇到的计算机有关。我真的记不起一个例子了。