为什么%u%d不能在UNIX / LINUX上用于打印地址

时间:2015-10-25 09:11:38

标签: c linux unix pointers

我知道%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上出错。

ERROR:

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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

  

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

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

如果您想控制输出,则另一个选项是使用uintptr_t提供的#include <inttypes.h>