92

I want to print out a variable of type size_t in C but it appears that size_t is aliased to different variable types on different architectures. For example, on one machine (64-bit) the following code does not throw any warnings:

size_t size = 1;
printf("the size is %ld", size);

but on my other machine (32-bit) the above code produces the following warning message:

warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'

I suspect this is due to the difference in pointer size, so that on my 64-bit machine size_t is aliased to a long int ("%ld"), whereas on my 32-bit machine size_t is aliased to another type.

Is there a format specifier specifically for size_t?

PJTraill
  • 1,232
  • 12
  • 28
Ethan Heilman
  • 14,869
  • 10
  • 58
  • 88
  • 1
    Your warning message does not match the code. The warning mentions pointers, your code doesn't have any. Did you remove some `&` somewhere? – Jens Apr 17 '12 at 14:38
  • Pointers? No I don't get any warnings about pointers, in fact depending on what machine I run that code on sometimes I get no warnings at all. Try the following test code: #include int main(){ size_t size = 1; printf("the size is %ld", size); return 0; } – Ethan Heilman Apr 17 '12 at 16:39
  • 2
    See also [Cross platform format string for variables of type size_t?](http://stackoverflow.com/questions/174612/cross-platform-format-string-for-variables-of-type-size-t). – legoscia Sep 21 '12 at 10:10
  • 1
    @EthanHeilman He's referring to the fact that your warnings say `warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'` when it probably _should_ be saying `warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'`. Were you maybe using `scanf()` instead when you got these warnings? – RastaJedi Aug 20 '16 at 19:04
  • 1
    Possible duplicate of [What's the correct way to use printf to print a size\_t?](http://stackoverflow.com/questions/940087/whats-the-correct-way-to-use-printf-to-print-a-size-t) – phuclv May 06 '17 at 09:13

3 Answers3

129

Yes: use the z length modifier:

size_t size = sizeof(char);
printf("the size is %zu\n", size);  // decimal size_t ("u" for unsigned)
printf("the size is %zx\n", size);  // hex size_t

The other length modifiers that are available are hh (for char), h (for short), l (for long), ll (for long long), j (for intmax_t), t (for ptrdiff_t), and L (for long double). See §7.19.6.1 (7) of the C99 standard.

anatolyg
  • 23,079
  • 7
  • 51
  • 113
Adam Rosenfield
  • 360,316
  • 93
  • 484
  • 571
  • whats the difference between zd and zu? I get that zd is decimal, but is it signed, if so how does zd being signed effect things. – Ethan Heilman Jan 24 '10 at 03:51
  • 1
    It's the difference between a `size_t` and an `ssize_t`; the latter is seldomly used. – Adam Rosenfield Jan 24 '10 at 03:53
  • 26
    Right, so in this case, you should be using `%zu`, because the argument is unsigned. – caf Jan 24 '10 at 23:03
  • The other options available are explained in the printf manual page: http://linux.die.net/man/3/printf – INS Jan 07 '14 at 22:00
  • Is this also part of C89/90? – detly Mar 24 '14 at 22:53
  • 9
    @detly: No, the `z` length modifier is not part of C89/C90. If you're aiming for C89-compliant code, the best you can do is cast to `unsigned long` and use the `l` length modifier instead, e.g. `printf("the size is %lu\n", (unsigned long)size);`; supporting both C89 and systems with `size_t` larger than `long` is trickier and would require using a number of preprocessor macros. – Adam Rosenfield Mar 25 '14 at 06:01
46

Yes, there is. It is %zu (as specified in ANSI C99).

size_t size = 1;
printf("the size is %zu", size);

Note that size_t is unsigned, thus %ld is double wrong: wrong length modifier and wrong format conversion specifier. In case you wonder, %zd is for ssize_t (which is signed).

maxschlepzig
  • 27,589
  • 9
  • 109
  • 146
1

MSDN, says that Visual Studio supports the "I" prefix for code portable on 32 and 64 bit platforms.

size_t size = 10;
printf("size is %Iu", size);
Arkantos
  • 79
  • 5
  • 6
    it's MS specific, which is not standard conforming, so it's not platform independent – phuclv Jun 24 '16 at 07:24
  • @phuclv Indeed. And if it really does say - as the answer suggests - 'portable' it's even worse than I ever knew about MS. Not that it would surprise me... I'm not one to downvote because someone went through the effort to try and answer something but still this answer is just wrong. Ah, I think I understand the idea here in 'portable'. It must be saying that it works for both 32-bit and 64-bit. But of course it would. – Pryftan Dec 03 '19 at 15:00