2

我有在 2 个项目/平台中运行的代码。它适用于一个,而不是另一个。代码是这样的:

uint8_t val = 1;
uint8_t buff[16];
sprintf(buff, "%u", val);

预期输出为“1”(gcc),但在一个编译器(Keil)上,它返回“511”,十六进制为 0x1FF。看起来它没有使用此编译器将字节提升为 int。这已得到确认,因为如果我这样做,它可以正常工作:

sprintf(buff, "%u", (int)val);

我的问题是:为什么一个编译器会做我认为“正确的事情”,而另一个却没有?是我不正确的期望/假设、编译器设置还是其他原因?

4

2 回答 2

2

为了获得最大的可移植性,您可以使用以下宏inttypes.h:(还有其他)

PRId8, PRIx8, PRIu8 PRId16, PRIx16, PRIu16 PRId32, PRIx32, PRIu32

通常(如我所料):

#define PRIu8 "u"

但是对于这种情况下的 Keil 编译器:

#define PRIu8 "bu"

例如,

printf("0x%"PRIx8" %"PRIu16"\n", byteValue, wordValue);

不过这很麻烦。我建议更友好的编译器。

令人惊讶的是,即使在做了几十年之后,你对这些东西都不了解。

于 2015-11-17T00:51:48.247 回答
1

你的假设可能是正确的,也可能是不正确的。这取决于编译器的实现。所有现代(或者应该说是智能)编译器都会像你提到的那样做。但是 Keil,从版本开始。9.02,您需要为 printf 指定正确的可变长度。

这是 Keil C 处理各种 printf 函数的方式。您需要准确指定它的长度。所有正则都是 16 位(无符号)整数,包括 %d、%x 和 %u。对 8 位使用修饰符“b”,对 32 位使用修饰符“l”。如果你给了错误的长度,你会得到错误的数字。更糟糕的是,其余的变量都是错误的。例如,要使用 8 位 'char',您使用 '%bd'(%bu 和 %bx),而 %ld、%lu 和 %lx 用于 32 位 'long'。

char c = 0xab;
printf("My char number is correctly displayed as '0x%02bx'\n", c);

还要注意,同样,要从 sscanf 获取数字数据,也是一样的。以下示例是使用 sscanf 获取 32 位长变量:

long var;
char *mynum = "12345678";
sscanf(mynum, "%ld", &var);

变量 var12345678后包含数字sscanf。下面显示了 Keil 的 printf 系列中使用的变量的长度。

%bd, %bx, %bu - 应该用于 8 位变量

%d, %x, %u - 应该用于 16 位变量,并且

%ld, %lx, %lu - 应该用于 32 位变量

于 2015-11-06T22:20:03.687 回答