[英]Why do I see a bigger value when I cast pointer to unsigned int as unsigned long long pointer?
以下程序的输出是:
dat:18446721190124690902 892374
dat:892374 892374
当我将变量“a”作为指针传递时会发生什么? 我希望两个函数都能打印相同的值。
#include <stdio.h>
void func(unsigned long long * dat) {
printf("dat : %llu %u \n",*dat,*dat);
}
void func1(unsigned long long dat) {
printf("dat : %llu %u \n",dat,dat);
}
int main(void)
{
unsigned int a;
a = 892374;
func((unsigned long long *) &a);
func1((unsigned long long) a);
return 0;
}
您正在尝试未定义的行为,因为unsigned int的大小小于unsigned long long。 就func
而言, dat
指向的内存长度为8个字节,实际上它只有4个字节 - 所以它访问了包含随机值的额外4个字节。 你将它转换回printf
的%u部分的unsigned int,所以它不使用额外的4个字节,所以你得到了正确的值。
第二个函数正常工作,因为它将值转换为unsigned long long,因此大小差异不是问题。
假设int是4个字节,long long是平台中的8个字节。 当您将长整型指针强制转换为长指针时,程序将尝试从指针指向的地址读取8个字节。
技术上没有人知道发生了什么,因为你的程序表现出不确定的行为。 但是,我们可以基于常见的体系结构(例如x86或x86_64)进行有根据的猜测。
第一个问题是演员:
func((unsigned long long *) &a);
您转换指针但不指向它指向的值。 在许多常见的机器上, int
将是32位值,而unsigned long long
是64位。 a
是32位长,但是您将指针传递给64位块。 在32位以上a
在存储器中可以是任何东西。 这就是为什么第一次打印打印真正长二进制数的原因。
在func1
,您正确施放a
这样的计划将延长a
,当它把它在堆栈上为64位。
在这两种情况下, printf
的最后一个参数的格式说明符都不正确。 printf
假设它已经传递了32位值,并且以某种方式忽略了传递的前32位,可能是因为它是在64位寄存器中传递的。 它是未定义的行为,它可以做它喜欢的事情。
在func1中,您将值复制为long long,因此值保持不变。 在func中,你正在复制内存地址,然后告诉编译器只是将它视为指向64位内存而不是它。 它正在读取你没有设置的内存。
如果您在调用时删除演员,编译器会停止/警告您:
func(&a);
func1(a);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.