我在嵌入式系统上使用平台/编译器(特别是PIC上的XC8),它不包含printf()的%p指针地址格式说明符。
例如:
printf("J: %f [@ 0x%p]\r\n", j, &j);
将显示大多数编译器中名为“j”的变量的值和地址。但是,根据编译器文档,它不包括对%p的支持。给出错误“无效的格式说明符或类型修饰符”。
那么在这种情况下,打印变量地址的替代方法是什么?
答案 0 :(得分:3)
名义上,您将使用<inttypes.h>
标头,uintptr_t
类型以及PRIXPTR
或PRIxPTR
格式(首先在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*));
只是为了(几乎)确保转换不会丢失信息。