是否存在 %p 格式说明符不会以 0x.. 格式打印地址的情况

Is there any case where %p format specifier will not print address in 0x.. format

在 C 中,我从控制台读取一个地址并将其存储在一个变量中。 我需要以十六进制 (0x...) 格式记录地址。

我有两个选择:

  1. %p
  2. %x

我试过选项 2 (%x)。它在 32 位和 64 位平台上的工作方式不同。这导致了不准确的程序行为。

现在第二个选项 (%p) 也是实现定义的。

所以我想知道应该使用哪个来在所有编译器和平台上保持一致的行为。

C 标准不保证任何打印指针的方法在所有实现中都完全“一致”,并且不能这样做,因为指针本质上特定于内存模型,而内存模型不受 C 标准控制。

您可以控制打印指针的某些方面,例如通过将其转换为 uintptr_t 并使用通常的 printf 转换控件来确保它始终以十六进制打印:

#include <inttypes.h> // Define PRIxPTR.
#include <stdint.h>   // Define uintptr_t.
#include <stdio.h>    // Declare printf.

void PrintPointer(const volatile void *p)
{
    printf("0x%08" PRIxPTR, (uintptr_t) p);
}

这将确保使用十六进制打印指针来表示其位。 uintptr_t 必须包含足够的信息来重现指针值(或等效值),因此显示必须包含有关指针的足够信息。但是,位的顺序和含义未由 C 标准定义。 08 保证至少打印八位数字(根据需要使用前导零),这使您在 32 位和 64 位指针的混合体系结构中具有一定的一致性,但 C 实现可以使用任意数量的位,因此指针可以打印更多的数字。如果您不考虑将位数固定为“一致”格式的一部分,则可以只使用 "0x%"

uintptr_t 类型是可选的,但很可能在现代 C 实现中提供。

(constvolatile 限定符与例程本身无关;包含它们只是为了让带有或不带有它们的指针都可以传递给例程,而不会受到例程的抱怨编译器。)