【问题标题】:how to printf 0x0000000 instead of (nil) and 0x08ffffff instead of 0x8ffffff in c如何在c中打印0x0000000而不是(nil)和0x08ffffff而不是0x8ffffff
【发布时间】:2021-05-06 21:37:07
【问题描述】:

我正在尝试使用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 来调整输出打印?

【问题讨论】:

  • 将其转换为uintptr_t 并按照stackoverflow.com/questions/5795978/… 中的说明进行打印
  • printf("start %08x and end %08x\n", (uint32_t)ptr1, (uint32_t)ptr2);
  • @WilliamPursell 非常糟糕的主意,因为 64 位环境越来越普遍。
  • @WilliamPursell 我收到此错误error: ‘uint32_t’ undeclared (first use in this function) printf("%08x - %08x RW\n",(uint32_t)regions[i].from,(uint32_t)regions[i].to);
  • @Hadi 如果您有机会在 64 位环境中编译此代码,那么无论如何您都不想像这样使用uint32_t

标签: c pointers printf stdout


【解决方案1】:

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

其次,标题<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");
}

更好的是,您可以在 C 实现中将字段宽度调整为 uintptr_t 的大小,方法是包含 &lt;limits.h&gt; 并计算所需的位数:

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

请注意,像初始化ptr1ptr2 那样直接设置指向硬编码常量值的指针很少见。它通常用于用硬件做一些特殊的事情。当您有意将整数转换为指针时,应使用强制类型转换以避免编译器警告。

【讨论】:

  • (sizeof u * CHAR_BIT + 3) / 4 如何在我的 9 位字符/18 位地址计算机上工作:-P
  • @AnttiHaapala:好的。
  • 请注意,符合标准的系统可能不支持 uintptr_t 。在这种情况下,我们可以遍历数字的字节(通过所需的任何方法获得)一次打印两个半字节
  • @MM:好吧,我会为此编写代码,但为了支持它和非 8 CHAR_BIT 实现,我们必须编写代码来处理跨实现的“字节”拆分的十六进制数字,” 即保持一个位移缓冲器。或者以其他方式容纳奇数大小的字节。我想我现在不会走那么远。
猜你喜欢
  • 2017-03-20
  • 2022-09-27
  • 1970-01-01
  • 2016-03-06
  • 2021-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多