C 双指针指向int变量以覆盖内存
我直接输入代码C 双指针指向int变量以覆盖内存,c,pointers,memory,int,double,C,Pointers,Memory,Int,Double,我直接输入代码 #include <stdio.h> struct A { int a; int b; }; int main() { struct A test; double *p = (double *)&(test.a); *p = 5; printf("variable a: %d\n", &test.a); printf("variable b: %d\n", &test.b); r
#include <stdio.h>
struct A
{
int a;
int b;
};
int main()
{
struct A test;
double *p = (double *)&(test.a);
*p = 5;
printf("variable a: %d\n", &test.a);
printf("variable b: %d\n", &test.b);
return 0;
}
为什么变量
a
是0x 0000
而b
是0x4014 0000
?代码的行为未定义
一旦将p
设置为非double
类型的某个对象的地址,就不能取消引用
要查看编译器对此输入所做的操作,请检查生成的程序集。代码的行为未定义 Clang编译器生成警告消息:
source_file.c:13:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d\n", &test.a);
~~ ^~~~~~~
source_file.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d\n", &test.b);
~~ ^~~~~~~
这是未定义的行为。另外,
double
5对应于64位整数0x40140000000000000
,因此您可能可以知道发生了什么。提示:double
可以大于int
。您会得到意外的结果,因为您对编译器撒了谎,它找到了报复您的方法。您告诉编译器,&(test.a)
是一个双精度的地址,但它是一个整数的地址。您可以随意调整优化设置,让编译器编译结果与代码不匹配的代码。@Bathsheba刚刚在这里写到输出与代码不匹配,所以,你为什么要推翻我的否决票?!该代码是一个严格的别名冲突,因此是完全未定义的行为。对未定义行为的影响进行推理是毫无意义的。在我的计算机中,int
占用4个字节,double
占用8个字节,我使用双指针指向int和赋值,它应该覆盖变量b的值,所以我认为b应该是5,a应为0。1075052544
是一个固定值,不会随每次运行或更改优化而更改。您可以想什么就想什么。这显然不是正在发生的事情。事实仍然是,行为未定义。双精度5对应于64位整数0x401400000000
。因此我得到b
是0x4014 0000
,变量b的值是4个字节的另一半。@UKeeySDis:您可以通过将64位整数设置为给定值,将双精度设置为另一个值,并调用memcmp
。所有完美定义的行为。这确实是一个好主意,我验证它。但是为什么双5对应于64位整数0x401400000000
?它是如何存储的?非常感谢。
source_file.c:13:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d\n", &test.a);
~~ ^~~~~~~
source_file.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d\n", &test.b);
~~ ^~~~~~~