【问题标题】:Why does %u %d not work on UNIX/LINUX for printing addresses [duplicate]为什么 %u %d 在 UNIX/LINUX 上不能用于打印地址 [重复]
【发布时间】:2015-10-25 09:11:38
【问题描述】:

我知道 %d 代表 int,%u 代表 unsigned int,%p 代表地址。 但我的问题是我们可以在 Windows 机器上使用 %u,%d 打印地址,但在 Linux 上却不能这样做。

例如:

#include<stdio.h>

int main() {
    int x=15;
    int *p;
    p=&x;

    printf("%d \n",x);
    printf("%d \n",&x);
    printf("%u \n",&x);
    printf("%p \n",p);
    printf("%x \n",p);
    printf("%u \n",&p);

return 0;   
}

输出:

15
2358812
2358812
000000000023FE1C
23fe1c
2358800

可以看出,使用 %d 和 %u 将十六进制值(23fe1c)更改为十进制。

但完全相同的代码在 Unix/Linux 上会出错。

错误:

format (%d) expects arguments of type 'int', but argument 2 has type 'int*'

【问题讨论】:

  • 将不匹配的数据提供给printf 会导致未定义的行为。您在 Windows 上的编译器意外接受了它,但 Linux 上的编译器没有。
  • 请注意,%p 用于打印void*,因此您应该在将指针传递给printf 之前将其转换为printf("%p \n",(void*)p);,即printf("%p \n",(void*)p);
  • 为了清楚起见,您不能使用%d 打印指针值,因为指针不是整数。整数不是指针。仅仅因为使用%d 打印指针在某些平台上工作并不意味着它可以在任何地方工作。但是将指针视为整数是错误的 - anywhere。当您开始进行 64 位编程时,您将很难学到这一点。

标签: c linux unix pointers


【解决方案1】:

GCC 能够对可变参数函数执行类型检查,特别是使用format function attribute。这会强制检查作为可变参数传递的类型是否与提供的格式字符串完全匹配。

【讨论】:

    【解决方案2】:

    GCC 报错是因为 printf 格式字符串中使用的数据类型和传递的参数不兼容。打印指针的可移植和标准方法是使用 %p 说明符。但是,您可以找到人们可能出于相同目的使用 %x 的其他地方。正如其他人所说,使用 %u 和 %d 与指针数据类型不兼容。它们可能适用于某些编译器,例如 Windows 案例,但其他更严格的编译器(如本案例中的 GCC)可能会抱怨传递的数据类型,因为 intint* 不同强>。为了使用 %p 表示法,您必须将指针强制转换为 void,如 C99 标准:

    p 参数应该是一个指向 void 的指针。指针的值以实现定义的方式转换为打印字符序列。

    也就是说,%p 是实现定义的,因此输出可以从一个实现更改为另一个。一般来说,使用 %d 或 %u 打印指针的任何方式都不是一个好主意。根据实现,指针可以是简单的 int 或 long int。因此,如果您尝试在地址存储在 long int 变量中的机器上使用 %d 或 %u 打印指针,您可能会得到未定义的行为。

    如果您想控制输出,那么另一种选择是使用#include &lt;inttypes.h&gt; 提供的uintptr_t

    【讨论】:

    • "根据实现的不同,指针可以是简单的 int 或 long int。" 它甚至可以是 两个 整数。
    • 您是指编译器使用 4 字节整数的 64 位机器的情况?
    • 不,我指的是分段地址,例如:0xabcd:0x1234(进一步阅读:en.wikipedia.org/wiki/X86_memory_segmentation
    • 实际上%p 在 (a) 64 位地址变得普遍并且 (b) 后来 gcc 添加了一个警告以指出这是一个问题时获得了关注。分段地址很值得警告,但逾期 20 年表明它们不是 gcc 警告的一个因素。
    猜你喜欢
    • 2011-07-09
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多