【问题标题】:A win32 vs x64 code comparisonwin32 与 x64 代码比较
【发布时间】:2013-09-03 07:16:09
【问题描述】:

我正在玩一些代码:

    int n;
    char *ptr;
    scanf("%d",&n); 
    ptr = (char *) &n; // pointer to the integer
    printf("\na[0]=%p",*ptr); // print the values at the next 4 memory locations
    printf("\na[1]=%p",*(ptr+1));
    printf("\na[2]=%p",*(ptr+2));
    printf("\na[3]=%p",*(ptr+3));

这段代码给了我一个干净的输出

FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF

对于 VisualC++ '12 中 win32 设置的输入 -1。

但是,当我为 x64 架构编译此代码时,我得到 -

00000000FFFFFFFF
00000000FFFFFFFF
00000000FFFFFFFF
00000000FFFFFFFF

对于相同的输入值-1。两种架构的整数大小相同。 我的问题是为什么 4 个位置的内存布局不都是 F?

【问题讨论】:

  • 您在滥用%p。请改用%x
  • @cnicutar 这就是重点。如果您使用 %p 在该位置打印内容,您会看到 MSB 填充为 0。
  • %p 想要一个void *,而你传递了一个char(被提升为int)。
  • 您没有发现打印 a byte 并获得 FFFFF (16 bits) 的问题吗?奶奶,你有多大的字节!
  • @Samboy786: %p 需要一个 8 字节的参数,但您传递的是一个 4 字节的参数(因为 char 在可变参数列表中被提升为 int)。从可变参数到格式说明符的“预期类型”没有魔法转换。行为未定义。

标签: c 64-bit


【解决方案1】:

printfp 说明符需要 void *。相反,您传递的是int(练习:为什么它是int?),因此行为未定义。为要打印的内容使用正确的说明符(cxu,也许?)。

【讨论】:

  • 但是如果我给它一个 void* 类型的 ptr,这实际上是如何工作的。 AFAIK 我可以修改任何类型为 void* 的数据(接受从一个地方复制到另一个地方)。我试过给它 %x - 它只截断 32/64 位字段中的前导 0。我也很确定更改 typcast 基本上不会更改数据(它只发生在最罕见的 DS 情况下)。
【解决方案2】:

%p*ptr 的行为不符合 OP 的预期。

printf("\na[0]=%p",*ptr); // print the values at the next 4 memory locations

ptr 的地址值为int n。注意:ptr 的类型仍然是一个指向char 的指针。 *ptr 说要取消引用 ptr 得到 charchar 的 8 位值是 0xFF,因为它是 n 的字节之一,肯定是 0xFFFFFFFF (-1)。这个char 被提升为int,因为它是printf() 的可变参数。因此 0xFF 变为 0xFFFFFFFF 因为int 在您的机器上可能是一个 4 字节整数。 printf() 看到 %p 格式说明符,因此期望在“VisualC++ '12”中看到一个 4 字节指针。这就是你的输出。在“x64”上,需要一个 8 字节的指针,但只定义了 4 个字节(0xFFFFFFFF)。它抓取的下一个 4 字节是未定义的,但结果是 0x00000000。因此你得到“00000000FFFFFFFF”。

下一行printf("\na[1]=%p",*(ptr+1))simple 得到n 的下一个char,也是0xFF。然后同样的提升到int,值为 0xFFFFFFFF。

怀疑 OP 想要

printf("\na[0] = 0x%08X",*  ((int *)ptr)  ); // print the values at the next 4 memory locations

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    相关资源
    最近更新 更多