Спецификаторы формата printf для uint32_t и size_t

У меня есть следующее

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

При компиляции я получаю следующее предупреждение:

format ‘%lu’ expects type ‘long unsigned int’, but argument has type ‘uint32_t’

Когда я запускал это с помощью splint, я получил следующее:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Большое спасибо за любой совет,

Ответ 1

Похоже, вы ожидаете, что size_t будет таким же, как unsigned long (возможно, 64 бит), когда на самом деле это unsigned int (32 бит). Попробуйте использовать %zu в обоих случаях.

Я не совсем уверен, хотя.

Ответ 2

Try

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

z представляет целое число длины, такое же, как size_t, а макрос PRIu32, определенный в заголовке C99 inttypes.h представляет неподписанное 32-битное целое число.

Ответ 3

Все, что нужно, это то, что спецификаторы формата и типы согласуются, и вы всегда можете сделать это, чтобы сделать это истинным. long составляет не менее 32 бит, поэтому %lu вместе с (unsigned long)k всегда корректно:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_t сложнее, поэтому %zu был добавлен в C99. Если вы не можете использовать это, тогда относитесь к нему так же, как k (long - самый большой тип в C89, size_t вряд ли будет больше).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Если вы не зададите спецификаторы формата для типа, который вы передаете, то printf будет делать эквивалент чтения слишком большого количества или слишком мало памяти из массива. Пока вы используете явные приемы для соответствия типам, они переносимы.

Ответ 4

Если вы не хотите использовать макросы PRI *, другой подход для печати целого типа ЛЮБОЙ - это использовать для intmax_t или uintmax_t и использовать "%jd" или %ju, соответственно. Это особенно полезно для типов POSIX (или других ОС), для которых не определены макросы PRI *, например off_t.