在C中,我从控制台读取一个地址并将其存储在一个变量中。我需要用十六进制(0x…(格式记录地址。
我有两个选择:
- %p
- %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实现中提供。
(const
和volatile
限定符与例程本身无关;它们的包含只是为了使带有或不带有它们的指针可以传递到例程,而不会受到编译器的抱怨。(