在C/C+中将int指针强制转换为长指针+;

在C/C+中将int指针强制转换为长指针+;,c,pointers,C,Pointers,假设我有下面的C代码 #include <stdio.h> int main(){ int a = 5; int b = 6; int c = 7; void *d = &a; long *ld = (long *)d; printf("%ld\n", *ld); return 0; } #包括 int main(){ INTA=5; int b=6; int c=7; void*d=&a; 长*ld=(长*)d; printf(“%ld\n”,*ld);

假设我有下面的C代码

#include <stdio.h>

int main(){ 
 int a = 5;
 int b = 6;
 int c = 7;
 void *d = &a;
 long *ld = (long *)d;
 printf("%ld\n", *ld);
 return 0;
}
#包括
int main(){
INTA=5;
int b=6;
int c=7;
void*d=&a;
长*ld=(长*)d;
printf(“%ld\n”,*ld);
返回0;
}
使用
gdb
执行
sizeof
,我可以看到在我的小端x64机器上,
int
是4个字节,
long
是8个字节

上述
printf
的输出为
5


我的问题是,尽管我的
ld
指针现在是64位的,并且指向
a
的第一个字节(32位可变),但值5是多少。当我去引用它时,它怎么不溢出?它如何不包括
b
c
中的字节?虽然是64位指针,但它如何知道在32位之后停止计数?

它是溢出的,并且,如第一条注释所述,它是未定义的行为

可能有不同的原因无法达到
b
c
。首先,由于没有使用它们,它们可能会被优化掉。若它们被使用,那个么,只要你们并没有得到它们的地址,它们就可以驻留在寄存器中。若它们在堆栈上,那个么堆栈上变量的顺序可能会不同,并且还可能添加填充


将这些连接到单个结构可能会阻碍优化和重新排序。使这种结构类型的变量成为全局变量更可能有效。但无论如何都不能保证,因为它仍然是未定义的行为。

行为应该是编译器和标志相关的。例如,您在我的测试中的确切代码:

% gcc x.c -W -Wall -O2
% ./a.out 
5
% gcc x.c -W -Wall -O0
% ./a.out 
-90829968375803

存储a、b、c的内存可能会被优化或重新排列,在堆栈上重新对齐取决于编译器和标志。

这是未定义的行为。任何事情都可能发生,甚至产生看似“正确”的结果。还可以查看是什么让您认为
b
的字节位于
a
的一侧,而
long
会拾取这些字节?是什么让你认为
b
的字节接近
a
?是什么让你认为
b
有任何字节,因为它没有被使用,可以通过优化删除?@EricPostpischil它们都在一个接一个的堆栈上,我用gdb确认了这是两种不同形式的未定义行为,关于结果的推理完全没有意思,因为没有任何输出的保证。