在C中,我想使用printf来显示指针,以便它们正确排列,我想用0填充它们。
我的猜测是,正确的方法是:
printf("%016p", ptr);
这有效,但是这个gcc抱怨以下消息:
warning: '0' flag used with ‘%p’ gnu_printf format
我已经用Google搜索了一下,以下主题是关于同一主题的,但并没有真正给出解决方案。
http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg00484.html
阅读它,似乎gcc抱怨的原因是我建议的语法没有在C99中定义。但我似乎无法找到任何其他方式以标准批准的方式做同样的事情。
所以这是双重问题:
答案 0 :(得分:38)
#include <inttypes.h>
#include <stdint.h>
printf("%016" PRIxPTR "\n", (uintptr_t)ptr);
但它不会以实现定义的方式打印指针(对于8086分段模式,请说DEAD:BEEF
)。
答案 1 :(得分:8)
使用:
#include <inttypes.h>
printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);
或者使用该标头中的宏的另一种变体。
另请注意,printf()
的某些实现会在指针前打印一个“0x
”;其他人没有(根据C标准,两者都是正确的)。
答案 2 :(得分:5)
打印指针值的唯一可移植方法是使用"%p"
说明符,它产生实现定义的输出。 (转换为uintptr_t
并使用PRIxPTR
可能会有效,但是(a)uintptr_t
是在C99中引入的,因此某些编译器可能不支持它,并且(b)它不能保证即使在C99中也存在(可能没有足够大的整数类型来保存所有可能的指针值。
因此,使用"%p"
与sprintf()
(或snprintf()
,如果有的话)打印到字符串,然后使用前导空格打印字符串填充。
一个问题是确定由"%p"
生成的字符串的最大长度没有很好的方法。
这无疑是不方便的(当然你可以把它包装在一个函数中)。如果您不需要100%的可移植性,我从未使用系统将指针转换为unsigned long
并使用"0x%16lx"
打印结果将无效。 [更新:是的,我有。 64位Windows有64位指针和32位unsigned long
。(或者你可以使用"0x%*lx"
计算宽度,可能类似于sizeof (void*) * 2
。如果你真的是偏执狂,您可以考虑CHAR_BIT > 8
的系统,因此每个字节将获得超过2个十六进制数字。)
答案 3 :(得分:4)
这个答案类似于之前在https://stackoverflow.com/a/1255185/1905491中给出的答案,但也考虑了可能的宽度(由https://stackoverflow.com/a/6904396/1905491概述,直到我的答案在其下面呈现,我才认识到这一点;)。以下剪切将在sane *机器上将指针打印为8个0通过的十六进制字符,其中它们可以由32位表示,16位在64b上,16位在16b系统上。
#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))
printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);
注意使用星号字符来获取下一个参数的宽度,该参数位于C99(可能在之前?),但很少见到“野外”。这比使用p
转换更好,因为后者是实现定义的。
*标准允许uintptr_t
大于最小值,但我认为没有实现不使用最小值。
答案 4 :(得分:0)
如果将指针强制转换为long类型,则很容易解决。问题是这不适用于所有平台,因为它假定一个指针可以放在一个long内,并且一个指针可以显示为16个字符(64位)。然而,在大多数平台上都是如此。
所以它会变成:
printf("%016lx", (unsigned long) ptr);
答案 5 :(得分:0)
正如您的链接所示,行为未定义。我不认为这是一种可行的方式,因为%p本身取决于您正在处理的平台。您当然可以将指针强制转换为int并以十六进制显示:
printf("0x%016lx", (unsigned long)ptr);
答案 6 :(得分:0)
也许这会很有趣(来自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和强制转换(强制转换和格式说明符非常不可移植)仅使用零。
答案 7 :(得分:0)
请注意,如果指针打印时使用&#34; 0x&#34;前缀,你需要替换&#34;%018p&#34;补偿。
答案 8 :(得分:-1)
我通常使用%x来显示指针。我认为它不能移植到64位系统,但它适用于32位。
我会对便携式解决方案的答案感兴趣,因为指针表示不是完全可移植的。