当我将指向unsigned int的指针转换为unsigned long long指针时,为什么会看到更大的值?

时间:2017-05-24 10:12:58

标签: c

以下程序的输出是:

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;
}

4 个答案:

答案 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);