Zos*_*oso 2 c pointers strict-aliasing language-lawyer type-punning
https://kukuruku.co/post/i-do-not-know-c/
问题#7:
#include <stdio.h>
void f(int *i, long *l)
{
printf("1. v=%ld\n", *l); /* (1) */
*i = 11; /* (2) */
printf("2. v=%ld\n", *l); /* (3) */
}
int main()
{
long a = 10;
f((int *) &a, &a);
printf("3. v=%ld\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
小端系统上两个不同编译器的输出是:
1. v=10 2. v=11 3. v=11
1. v=10 2. v=10 3. v=11
Run Code Online (Sandbox Code Playgroud)
第二个结果怎么可能?我通过引用严格别名来解释结果的解释并不完全.编译器是否完全忽略第(2)行?
引用维基百科:
在C或C++中,由严格别名规则强制要求,如果函数中的指针参数指向 基本上不同的类型,则假定它们不是别名,除了char*和void*,它们可能是任何其他类型的别名.某些编译器允许关闭严格别名规则,因此任何指针参数都可以为任何其他指针参数设置别名.在这种情况下,编译器必须假定通过这些指针的任何访问都可以是别名.这可以防止进行一些优化.
这是违反规则的地方:
f((int *) &a, &a);
^ aliasing to different type (a is 'long')
^ passing the same variable with different type
Run Code Online (Sandbox Code Playgroud)
问题是假设严格的别名规则,函数的第一个和第二个参数指向另一个位置,因为它们是不同类型的.这就是作者解释的原因:
因此,我们可以假设任何长期都没有改变.
在这里:取消引用printf("2. v=%ld\n", *l);一个long值.
这就是为什么这部分(2)在两个编译器上都是未定义的行为.