什么是正确使用printf来显示用0填充的指针
在C中,我想使用printf来显示指针,并使它们正确排列,我想用0填充它们。
我的猜测是,正确的做法是:
printf(“%016p”,ptr);
这工作,但这个海湾合作委员会抱怨以下消息:
警告:与'%p'gnu_printf格式一起使用'0'标志
我已经google了一下,下面的线程是在同一个主题,但并没有真正给出解决scheme。
http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html
阅读它,似乎gcc抱怨的原因是我提出的语法没有在C99中定义。 但我似乎无法find任何其他方式以标准认可的方式来做同样的事情。
所以这里是双重的问题:
- 我的理解是正确的,这种行为不是由C99标准定义的?
- 如果是这样,是否有一个标准的批准,便携式的方式呢?
#include <inttypes.h>
#include <stdint.h>
printf("%016" PRIxPTR "\n", (uintptr_t)ptr);
但是它不会以实现定义的方式打印指针( DEAD:BEEF
8086分段模式的DEAD:BEEF
)。
使用:
#include <inttypes.h> printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);
或者使用该头部的macros的另一个变种。
还要注意一些printf()
实现在指针前面打印一个' 0x
' 别人没有(根据C标准都是正确的)。
打印指针值的唯一便携方法是使用"%p"
说明符,它生成实现定义的输出。 (转换为uintptr_t
并使用PRIxPTR
很可能会工作,但(a) uintptr_t
是在C99中引入的,因此有些编译器可能不支持它,(b)即使在C99中也不能保证存在(可能不是整数types足够大以容纳所有可能的指针值。
因此,使用sprintf()
(或snprintf()
,如果有的话)的"%p"
打印到一个string,然后打印string填充前导空白。
一个问题是,确定由"%p"
生成的string的最大长度没有真正的好方法。
这当然是不方便的(当然,你可以把它包装在一个函数中)。 如果你不需要100%的可移植性,我从来没有使用过将指针转换为unsigned long
的系统,而使用"0x%16lx"
打印结果将不起作用。 (或者你可以使用"0x%*lx"
来计算宽度,可能类似于sizeof (void*) * 2
,如果你确实是偏执的话,那么你可以考虑CHAR_BIT > 8
系统,比每个字节2个hex数字)。
这个答案类似于之前在https://stackoverflow.com/a/1255185/1905491中给出的答案,但也考虑到了可能的宽度(如https://stackoverflow.com/a/6904396/1905491所述,其中I直到我的答案被呈现在它下面才认出);; 下面的内容将把指针打印为8位0-hex字符,它们可以由32位,64位和16位系统中的16位来表示。
#include <inttypes.h> #define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2)) printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);
请注意使用星号字符来获取宽度的下一个参数,这是在C99(可能之前?),但很less见“野外”。 这比使用p
转换更好,因为后者是实现定义的。
*标准允许uintptr_t
大于最小值,但是我认为没有使用最小值的实现。
如果将指针指向长types,则很容易解决。 问题是这不适用于所有的平台,因为它假定一个指针可以放在一个长的内部,并且一个指针可以以16个字符(64位)显示。 但是在大多数平台上都是如此。
所以它会变成:
printf("%016lx", (unsigned long) ptr);
由于您的链接已经build议,行为是不确定的。 我不认为有这样做的可移植方式,因为%p本身取决于您正在使用的平台。 你当然可以将指针转换为一个int值并以hex显示:
printf("0x%016lx", (unsigned long)ptr);
也许这将是有趣的(从一个32位的Windows机器,使用mingw):
rjeq@RJEQXPD /u $ cat test.c #include <stdio.h> int main() { char c; printf("p: %016p\n", &c); printf("x: %016llx\n", (unsigned long long) (unsigned long) &c); return 0; } rjeq@RJEQXPD /u $ gcc -Wall -o test test.c test.c: In function `main': test.c:7: warning: `0' flag used with `%p' printf format rjeq@RJEQXPD /u $ ./test.exe p: 0022FF77 x: 000000000022ff77
正如你所看到的,%p版本用指针的大小填充零,然后空格到指定的大小,而使用%x和强制转换(强制转换和格式说明符是非常不可移植的)只使用零。
请注意,如果指针以“0x”前缀打印,则需要replace“%018p”进行补偿。
我通常使用%x来显示指针。 我想这不是可移植到64位系统,但它对32位工作正常。
因为指针表示不完全是可移植的 ,所以我会对看到便携式解决scheme的答案感兴趣。