C sprintf разрывается с байтовыми параметрами (компилятор Keil)

У меня есть код, работающий в 2 проектах / платформах. Это работает в одном, а не в другом. Код выглядит так:

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

Ожидаемый результат - "1" (gcc), но на одном компиляторе (Keil) он возвращает "511", что в шестнадцатеричном формате равно 0x1FF. Похоже, это не продвигает байт к int с этим компилятором. Это подтверждается, потому что это работает нормально, если я сделаю это:

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

У меня такой вопрос: почему один компилятор делает то, что я считаю "правильным", а другой нет? Это мои неверные ожидания / предположения, настройки компилятора или что-то еще?

2 ответа

Решение

Ваше предположение может быть правильным или неверным. Это зависит от реализации компилятора. Все современные (или должны сказать умные) компиляторы будут делать то, что вы упомянули. Но Кейл, как вер. 9.02, вам нужно указать правильную переменную длину для printf.

Это способ Keil C обрабатывать все виды функций printf. Вы должны точно указать, как долго это будет. Все обычные для 16-битного (без знака) целого числа, включая%d, %x и% u. Используйте модификатор 'b' для 8-битных и 'l' для 32-битных. Если вы дали неправильную длину, вы получите неправильный номер. Что еще хуже, все остальные переменные неверны. Например, чтобы использовать 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 это тоже самое. Следующий пример - получить 32-битную переменную длиной с помощью sscanf:

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

Переменная var содержит число 12345678 после sscanf, Ниже показана длина переменных, используемых в семействе printf для Keil.

% bd,% bx,% bu - следует использовать для 8-битных переменных

%d, %x, %u - должны использоваться для 16-битных переменных, и

%ld, %lx, %lu - следует использовать для 32-битных переменных

Для максимальной переносимости вы можете использовать эти макросы из 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);

Это довольно громоздко, хотя. Я предлагаю более дружелюбные компиляторы.

Удивительно, что вы не знаете об этом материале даже после того, как проделали это десятилетиями.

Другие вопросы по тегам