以下程序的输出是:
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;
}
答案 0 :(得分:1)
您正在尝试未定义的行为,因为unsigned int的大小小于unsigned long long。就func
而言,dat
指向的内存长度为8个字节,而实际上它只有4个字节 - 所以它访问了包含额外的4个字节随机值。您将其转换回printf
的%u部分的无符号整数,因此它不会使用额外的4个字节,因此您可以获得正确的值。< / p>
第二个功能正常工作,因为它将值转换为无符号长多,因此尺寸差异不是问题。
答案 1 :(得分:1)
假设int是4个字节,long long是平台中的8个字节。 当您将长整型指针强制转换为长指针时,程序将尝试从指针指向的地址读取8个字节。
答案 2 :(得分:1)
从技术上讲,没有人知道发生了什么,因为你的程序表现出未定义的行为。但是,我们可以根据常见架构进行有根据的猜测,例如: x86或x86_64。
第一个问题是演员:
func((unsigned long long *) &a);
您投射指针但不指向它指向的值。在许多常见的机器上,int
将是32位值,unsigned long long
是64位。 a
是32位长,但是您将指针传递给64位块。内存中{32}以上的32位可能是任何东西。这就是为什么第一次打印打印真正长二进制数的原因。
在a
中,您正确地转换func1
,以便程序在将其置于堆栈时将a
扩展为64位。
在这两种情况下,a
的最后一个参数的格式说明符都不正确。 printf
假设它已经传递了32位值并且以某种方式忽略了传递的前32位,可能是因为它是在64位寄存器中传递的。它是未定义的行为,它可以做它喜欢的事情。
答案 3 :(得分:0)
在func1中,您将值复制为long long,因此值保持不变。 在func中,你正在复制内存地址,然后告诉编译器只是将它视为指向64位内存而不是它。它正在读取你没有设置的内存。
如果您在调用时删除演员,编译器会停止/警告您:
func(&a);
func1(a);