使用 COSMIC 编译器的 stm8l 上 printf 的奇怪行为

Weird behavior of printf on a stm8l with COSMIC compiler

printf 在某些情况下给了我奇怪的额外值。可能发生了什么?

我正在处理 uint8_t 数组中的值并将其打印到我的终端以验证一切是否正确。但是由于某种原因,当我打印 uint8_t 时我得到了奇怪的值 - 我得到了预期值加上一些其他值(它总是相同的额外值),就像我打印 uint16_t 或其他 16 位值。我将其全部缩减为以下示例:

这是测试代码

test_payload[0] = (uint8_t)0x58;
test_payload[1] = (uint8_t)0x7B;
test_payload[2] = (uint8_t)0x6B;
test_payload[3] = (uint8_t)0x05;
test_payload[4] = (uint8_t)0x4F;
test_payload[5] = (uint8_t)0x81;
test_payload[6] = (uint8_t)0x69;
test_payload[7] = (uint8_t)0x00;

printf("%x\n\r", test_payload[0]);
printf("%x\n\r", test_payload[1]);
printf("%x\n\r", test_payload[0] + test_payload[1]);

for(i = 0; i < 8; i++)
{
    printf("%x", test_payload[i]);
}

我得到的输出是

5803
7b03
d3
58037b0333034f03810369033

是什么让它表现如此?

%x 需要一个 unsigned int 作为参数;如果你想打印一个字节,例如作为uint8_t,你需要写%hhx.

第一个代码片段应生成 58,但您不输出换行符,因此任何后续输出都将出现在 58 之后。您可能会在片段后面的代码中输出 86。 Post 展示违规行为的完整程序,或将格式更改为 %x\n 以将 58 与后续输出分开。

从技术上讲,printf 需要一个 unsigned int 参数用于 %x 转换格式,但是 int 值应该可以正常工作并且 test_payload[0] 被提升为int 并传递给 printf。您可以尝试将格式更改为 %hhx 或将参数转换为 (unsigned int)test_payload[0],但非常令人惊讶 仅这些更改之一就解决了问题。

编辑: 从你的额外信息来看,你的嵌入式目标的编译器看起来很奇特。一定要尝试将参数转换为

printf("%x\r\n", (unsigned int)test_payload[0]);

观察到 printf("%x\n\r", test_payload[0] + test_payload[1]); 似乎工作正常,问题不是传递 int 而不是 unsigned int,这已经够糟糕了......似乎 printf() 以不一致的方式错误地传递了 uint8_t 值。

另一个潜在的问题来源是,如果您忘记包含 <stdio.h> 并且在没有原型定义的情况下调用 printf。 C 标准(6.5.2.2 函数调用)如果函数是已定义(在库中),则明确将此调用定义为具有未定义的行为包含省略号的原型 (...).