【问题标题】:Why would printf with %p pointer format specifier print garbage chars on AVR instead of an address?为什么带有 %p 指针格式说明符的 printf 会在 AVR 上打印垃圾字符而不是地址?
【发布时间】:2019-02-15 16:16:30
【问题描述】:

我看过How to find the address of a variable when using AVR? - 那里的结论基本上是:

printf()——在嵌入式目标上调试有点复杂,你需要仔细研究一下是否有代码可以将 printf() 与串口连接起来,等等。此外,完整的 printf() 可能有点重,因此您可能已经在使用精简的标准库。这不是编译器的责任,你需要弄清楚它是如何实现的。

...但我无法真正弄清楚为什么会出现这个问题。

我有一个变量,我想将其用作“字符串数组”,并且我想对其进行 malloc 和 realloc:

char** my_array = malloc(sizeof(char*)*1);

然后,我将printf 重定向到“打印”到 USB 串行端口,然后我在串行终端中读取打印输出。

据我所知,printf 的%p 格式说明符应该将变量的地址打印为十六进制数。我有这样的声明:

printf("my_array %p\r\n", (void *)&my_array);

我也试过了:

printf("my_array %p\r\n", &my_array);
printf("my_array %p\r\n", my_array);

在所有情况下,我得到的打印输出都是这样的:

my_array  ▒▒▒ꓣ▒▒▒▒/▒▒f'w'▒`$▒▒W*▒▒X▒f'w'▒`$▒▒Y*▒▒Z▒f'w'▒`▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒#▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒j▒{▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒i▒z▒▒`$▒▒

...这显然不是十六进制数。

为什么会发生这种情况,我做错了什么?以及如何在 AVR 中获取以十六进制数字形式打印的变量地址?如果重要,我使用 CodeVisionAVR 编译器...


编辑:发现这个:

https://www.avrfreaks.net/forum/format-specifier-pointers-0

但是人们真的会使用 %p,尤其是在 AVR 上。在 AVR 上,指针是 16 位无符号数。我通常会自己使用 %04X 或其他东西。

(好吧,刚刚意识到这个论坛可能意味着 32 位 ARM 或 UC3,我猜指针是 32 位的?即便如此 %08X 在那种情况下)

...所以我只使用了:

printf("my_array %08X\r\n", (void *)&my_array);

...现在我得到了打印输出:

my_array 00003FFB

...但现在我不知道这是否是实际地址:)

【问题讨论】:

    标签: c avr


    【解决方案1】:

    您可以将指针转换为 uintptr_t 并打印:

    printf("my_array %llu\r\n", (unsigned long long)(uintptr_t)&my_array);
    

    【讨论】:

    • 非常感谢 @dbush - 只是一些注意事项:我使用 8/16 位微控制器,对于 %llu/unsigned long long,我不断收到“错误:对于 64-位整数支持请使用'math64.h'”,即使我添加了#include <math64.h>。转到%lu/unsigned long 可以解决这个问题。 uintptr_t 需要 #include <stdint.h>。最后,%lu 打印一个十进制数,对于十六进制 (stackoverflow.com/questions/29509452),我最终使用了0x%08lX。现在,我得到0x00000014 而不是0x00003FFB,尚不确定它是否描述了实际地址-但至少解决了printf问题。
    • @sdbbs 不确定它是否描述了实际地址 — 你是对的,值 0x14 不能是 内存 地址在 AVR 中,因为它位于 IO 端口 tom 地址下方(甚至更多——在核心寄存器地址范围0x00-0x1F)。
    • 再注意一点:我已经尝试过与常规(不是双重,如 OP)char* mytest 类似的东西;我最终通过mytest == NULL 进行了检查,并通过该打印输出得知它确实为空;对于这种特殊情况,事实证明我应该写printf( "0x%08lX\r\n" , (unsigned long)(uintptr_t)mytest); - 没有“&符号”的“地址”;这就是将实际 0x0 打印为地址的内容(如果我添加 & 符号(如 (unsigned long)(uintptr_t)&mytest 中),那么我会得到这个 0x14 非地址。)
    • 终于找到了%p 产生损坏输出的原因 - printf 的 CodeVision AVR 手册指出:“'p' - 函数参数是指向位于in FLASH;" - 所以%p 与它在“桌面”C 中的含义不同,它以十六进制打印指针(这就是为什么我也在 OP 示例中打印字母的原因)
    • @sdbbs 请把它作为这个问题的答案发布
    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    相关资源
    最近更新 更多