繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM