替代"%p"格式说明符

时间:2015-02-13 01:34:41

标签: c embedded microcontroller

我在嵌入式系统上使用平台/编译器(特别是PIC上的XC8),它不包含printf()的%p指针地址格式说明符。

例如:

printf("J: %f [@ 0x%p]\r\n", j, &j);

将显示大多数编译器中名为“j”的变量的值和地址。但是,根据编译器文档,它不包括对%p的支持。给出错误“无效的格式说明符或类型修饰符”。

那么在这种情况下,打印变量地址的替代方法是什么?

2 个答案:

答案 0 :(得分:3)

名义上,您将使用<inttypes.h>标头,uintptr_t类型以及PRIXPTRPRIxPTR格式(首先在C99或ISO / IEC 9899中正式定义: 1999):

printf("J: %f [@ 0x%" PRIXPTR "]\r\n", j, (uintptr_t)&j);

但是,如果您没有%p,那么您可能也没有printf("J: %f [@ 0x%lX]\r\n", j, (unsigned long)&j); ,所以您可能不得不依赖:

sizeof(unsigned long) == sizeof(void *)

这假定为sizeof(other_integer_type) == sizeof(void *);如果没有,则需要使用整数类型{{1}}。如果您找不到这样的类型,您需要详细解释机器上的类型。

答案 1 :(得分:3)

%p格式通常由运行时库中的printf函数实现,而不是在编译器中实现。对于编译器和库不一定来自同一供应商或其他来源的实现,这种区别可能很重要。 (有些编译器可能会使用文字格式字符串优化printf次调用;感谢chux指出这一点。)

正如Matt McNabb的评论所暗示的那样,您很可能将指针转换为unsigned long并使用%lx进行打印。我可能会使用类似的东西:

printf("J: %f [@ 0x%lx]\r\n", j, (unsigned long)&j);

如果(a)指针宽于unsigned long或(b)从指针类型到unsigned long的转换丢失信息,则可能会失败。我曾在一些奇怪的系统上工作,但我从来没有见过会违反这些假设的人。

由于您的代码可能无论如何都不是可移植的,因此您可以在平台上检查指针和unsigned long的大小。如果您感到偏执,可以添加以下内容:

assert(sizeof (unsigned long) >= sizeof (void*));

只是为了(几乎)确保转换不会丢失信息。