Is the %zu specifier required for printf?

41,944

If size_t exists shouldn't zu also be available in printf?

size_t existed at least since C89 but the respective format specifier %zu (specifically the length modifier z) was added to the standard only since C99.

So, if you can't use C99 (or C11) and had to print size_t in C89, you just have to fallback to other existing types, such as:

printf("%lu\n", (unsigned long)n);
Share:
41,944
Trevor Hickey
Author by

Trevor Hickey

and programming

Updated on July 17, 2022

Comments

  • Trevor Hickey
    Trevor Hickey almost 2 years

    We are using C89 on an embedded platform. I attempted to print out a size_t, but it did not work:

    #include <stdio.h>
    int main(void) {
        size_t n = 123;
        printf("%zu\n",n);
        return 0;
    }
    

    Instead of 123, I got zu.
    Other specifiers work correctly.

    If size_t exists shouldn't zu also be available in printf?
    Is this something I should contact my library vendor about, or is a library implementation allowed to exclude it?

    • Kerrek SB
      Kerrek SB over 7 years
      The z prefix was added in C99 I believe.
    • Trevor Hickey
      Trevor Hickey over 7 years
      @KerrekSB Ok. It doesn't seem to be annotated. en.cppreference.com/w/cpp/io/c/fprintf
    • mch
      mch over 7 years
      Why should a C++ reference say anything about a C standard?
    • LPs
      LPs over 7 years
      The Man has it...
    • LPs
      LPs over 7 years
    • Cubbi
      Cubbi over 7 years
      Now marked on cppreference
    • Trevor Hickey
      Trevor Hickey over 7 years
      @mch Right. I meant to post the C reference.
  • supercat
    supercat over 7 years
    Note that the above code would be sufficient, though not necessarily efficient, on any platform where unsigned long was large enough to accommodate the largest possible value of n (regardless of whether it was large enough to handle the full range of size_t). There is no guarantee, however, that size_t won't be larger than unsigned long, and there might not be any guarantee that n would always fit in unsigned long. I don't know how often that would be a problem [many programs could run into different trouble if they calculate the size of sprintf buffers...
  • supercat
    supercat over 7 years
    ...based upon a presumption that the maximum length of a decimal-formatted unsigned long is 10 digits and the value to be output ends up being longer than that].
  • chqrlie
    chqrlie about 6 years
    For better portability, use printf("%llu\n", (unsigned long long)n);, unless you know that the size is small, such as sizeof(int) in which case you can simply write printf("%u\n", (unsigned)n);
  • P.P
    P.P over 5 years
    @chqrlie unsigned long long didn't exist in C89 - that's the reason I suggested unsigned long. If unsigned long long is available (C99), then %zu specifier for size_t would also be available. Thus there's no need to cast to unsigned long long here at all.
  • chqrlie
    chqrlie over 5 years
    The problem is actually located in the C library. A common case where %zu is not supported is older versions of MinGW that use gcc in combination with the system's Microsoft C library, which until very recently did not support most C99 extensions.