如何在 c 中打印 0x0000000 而不是 (nil) 和 0x08ffffff 而不是 0x8ffffff

how to printf 0x0000000 instead of (nil) and 0x08ffffff instead of 0x8ffffff in c

我正在尝试使用 stdout stream 来打印 0x00000000 而不是 (nil)0x08ffffff 而不是 0x8ffffff

所以基本上,char *ptr1 = 0x00000000char *ptr2 = 0x08ffffff

当我运行

printf("start of address is %p and end of address is %p", ptr1, ptr2);

我明白了

start of address is (nil) and end of address is 0x8ffffff

我实际上找到了解决这个问题的方法,我实际上会这样做:

char *ptr1 = 0x00000000; 
char *ptr2 = 0x08ffffff;
printf("start 0x%08x and end 0x%08x\n",ptr1, ptr2);

这会生成

start 0x00000000 and end 0x08ffffff

但是,编译器发出以下警告:

warning: format ‘%x’ expects argument of type ‘unsigned int’, 
but argument 3 has type ‘void *’ [-Wformat=]

我应该如何修改printf来调整输出打印?

首先,要控制地址的打印方式,您必须将它们转换为整数类型。 %p 打印指针的规范不充分。为此,您可以包含 <stdint.h> 并使用 uintptr_t 类型,这是一种无符号整数类型,适用于某些地址工作。

其次,header <inttypes.h> 提供了一个宏 PRIxPTR,它提供了一个 printf 转换说明符,用于以十六进制打印 uintptr_t 值。

第三,您可以添加一个标志 0 和一个最小字段宽度 8 以请求将零转换为至少八位数字。

示例代码如下:

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>

static void PrintAddress(const void *p)
{
    uintptr_t u = (uintptr_t) p;
    printf("0x%08" PRIxPTR, u);
}

int main(void)
{
    char *ptr1 = (char *) 0x00000000;
    char *ptr2 = (char *) 0x08ffffff;
    printf("Start of address is ");
    PrintAddress(ptr1);
    printf(" and end of address is ");
    PrintAddress(ptr2);
    printf(".\n");
}

更好的是,您可以通过包含 <limits.h> 并计算所需的位数来调整字段宽度以适应 C 实现中 uintptr_t 的大小:

    printf("0x%0*" PRIxPTR, ((int) sizeof u * CHAR_BIT + 3) / 4, u);

请注意,像初始化 ptr1ptr2 那样直接将指针设置为 hard-coded 常量值的情况很少见。它通常用于对硬件做特殊的事情。当你故意将整数转换为指针时,你应该使用强制转换以避免编译器警告。