[c] printf format specifiers for uint32_t and size_t

I have the following

size_t   i = 0;
uint32_t k = 0;

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

I get the following warning when compiling:

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

When I ran this using splint I got the following:

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

Many thanks for any advice,

This question is related to c printf

The answer is


Sounds like you're expecting size_t to be the same as unsigned long (possibly 64 bits) when it's actually an unsigned int (32 bits). Try using %zu in both cases.

I'm not entirely certain though.


If you don't want to use the PRI* macros, another approach for printing ANY integer type is to cast to intmax_t or uintmax_t and use "%jd" or %ju, respectively. This is especially useful for POSIX (or other OS) types that don't have PRI* macros defined, for instance off_t.


Try

#include <inttypes.h>
...

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

The z represents an integer of length same as size_t, and the PRIu32 macro, defined in the C99 header inttypes.h, represents an unsigned 32-bit integer.


All that's needed is that the format specifiers and the types agree, and you can always cast to make that true. long is at least 32 bits, so %lu together with (unsigned long)k is always correct:

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

size_t is trickier, which is why %zu was added in C99. If you can't use that, then treat it just like k (long is the biggest type in C89, size_t is very unlikely to be larger).

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

If you don't get the format specifiers correct for the type you are passing, then printf will do the equivalent of reading too much or too little memory out of the array. As long as you use explicit casts to match up types, it's portable.