使用 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 函数调用)如果函数是已定义(在库中),则明确将此调用定义为具有未定义的行为包含省略号的原型 (...
).
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 函数调用)如果函数是已定义(在库中),则明确将此调用定义为具有未定义的行为包含省略号的原型 (...
).