printf and %llu vs %lu on OS X

33,573

Solution 1

The macros are already defined for you in <cinttypes>. Try

printf("%"PRIu64, x);

Or, even better, use C++ features like

std::cout << x;

which will select the proper << operator for your variable type.

Solution 2

The answer is to promote via static cast:

some_type i = 5;
printf("our value is: %llu", (unsigned long long)i);

Solution 3

The underlying type of uint64_t can be whatever the implementation like as long as it is in fact 64 bits.

Obviously in C++ the preferred solution is to use iostreams instead of printf as then the problem disappears. But you can always just cast the value passed to printf to make the type always correct:

printf("%llu", static_cast<unsigned long long>(value));

Share:
33,573
Steven Lu
Author by

Steven Lu

Play a multitouch HTML5 Tetris clone -- http://htmltetris.com (Interesting note about this site. It used to be my site, then Tetris Co. sent me a cease and desist, then I forgot about it, and now it’s back: someone brought it back and put MY code back on the site.) A huge fan of tmux and vim.

Updated on July 31, 2022

Comments

  • Steven Lu
    Steven Lu over 1 year

    Possible Duplicate:
    how to printf uint64_t?

    Why is it that on my 64-bit Mac (I am using Clang) the uint64_t type is unsigned long long while on 64-bit Ubuntu the uint64_t type is unsigned long?

    This makes it very difficult for me to get my printf calls to not give compiler warnings (or indeed even to work) under both environments.

    I can try to use macros to try to choose the correct string (#define LU either %llu or %lu, and in the process uglifying the printf strings a bit) but on the Mac I've got a 64-bit word size (so _LP64 would be defined and UINTPTR_MAX != 0xffffffff) and yet it still uses long long for the 64 bit int types.

    // printf macro switch (for the uint64_t's)
    #if UINTPTR_MAX == 0xffffffff 
       // 32-bit
    #  define LU "%llu"
    #else 
       // assume 64-bit
       // special case for OS X because it is strange
       // should actually check also for __MACH__ 
    #  ifdef __APPLE__
    #    define LU "%llu"
    #  else
    #    define LU "%lu"
    #  endif
    #endif
    
  • Steven Lu
    Steven Lu over 11 years
    fatal error: 'cinttypes' file not found
  • Bo Persson
    Bo Persson over 11 years
    This is a C++11 header, so it depends on how compatible your compiler is. If supporting C99, there will be an <inttypes.h>.
  • Steven Lu
    Steven Lu over 11 years
    Ah, okay, thanks. I did actually find that file in the C++11 libc++. Well, hopefully this inttypes.h header is available on my other platforms as well, here's the replacement for my code snippet in the question: #define LU "%"PRIu64
  • Steven Lu
    Steven Lu over 11 years
    I have never seen %zu or %ju before. How standard is this?
  • daxnitro
    daxnitro over 11 years
    It's standard and should be perfectly portable. cplusplus.com/reference/cstdio/printf
  • Steven Lu
    Steven Lu over 11 years
    Oh wow. Must have missed it.
  • Steven Lu
    Steven Lu over 11 years
    Hmm... Lengthens the code a bit.
  • Johannes Overmann
    Johannes Overmann about 9 years
    The std::cout << x; statement is not equivalent to the printf(). If you write the equivalent statement you will see why people still use printf() to format numbers. :-)
  • Gonzalo Aguilar Delgado
    Gonzalo Aguilar Delgado almost 6 years
    %zu is for size_t data types, that differ in different platforms so you can make sure the correct interpretation is made. Is basically the formatting of a size_t as unsinged.