以下代码是否违反严格的别名?
int a = 0;
*((int *)((char *)&a)) = 1;
为什么不呢?,因为我们最终使用合法的a
来引用int int *
的指针
为什么?,因为我们将char *
强制转换为int *
并取消引用(int *
),这似乎是严格的别名冲突
答案 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
类型-这是完全有效的。