将指针转换为64位整数,为什么32位&的结果不同? 64位平台

时间:2017-02-11 16:12:21

标签: c

我有一个代码片段(up.cpp),如下所示:

#include <stdio.h>

typedef unsigned long long Uint64;
int main()
{
    void *p = (void*)0xC0001234;
    Uint64 u64 = (Uint64)p;
    printf("{%llx}\n", u64);

    return 0;
}

使用32位gcc 4.8.1进行编译,得到输出:

{ffffffffc0001234}

使用64位gcc 4.8.1进行编译,得到输出:

{c0001234}

是的,64位的值为32位。 gcc 4.8.1来自openSUSE 13.1。

我也尝试过Visual C ++ 2010 x86&amp; x64编译器(代码更改,__int64%I64x),并且令人惊讶地得到相同的结果。

当然,我打算在x86和x86上获得{c0001234}。 64。但为什么会有这样的差异?

1 个答案:

答案 0 :(得分:5)

的行为
Uint64 u64 = (Uint64)p;

不是由语言定义的。它是实现定义的。

虽然64位平台可能会将其实现为纯概念转换(指针“填充”整个目标值),但在32位平台上,实现面临两难:如何将32位指针值扩展到一个64位整数值,带符号扩展或没有?显然,您的实现决定对值进行签名扩展。

显然,您的实现认为在指向无符号指针的转换中,原始指针值应该作为排序的签名值。不过,这将是一个相当奇怪的决定。我无法在GCC中重现它:http://coliru.stacked-crooked.com/a/9089ccda625bd65d

如果您的平台上发生了这种情况,那么您应该能够通过首先转换为uintptr_t(作为中间类型)来抑制此行为,如评论中的@barak manos所示。