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
Unfortunately the standard's not very specific on the sizes of these types... The only guarantee is that
sizeof(int) <= sizeof(long) <= sizeof(long long)
.You can use macros like you said, or you could try using
%zu
or%ju
which are used to print outsize_t
anduintmax_t
types (both 64-bit on OS X, haven't tested on Ubuntu). I don't think there are any other options.The answer is to promote via static cast:
The macros are already defined for you in
<cinttypes>
. TryOr, even better, use C++ features like
which will select the proper << operator for your variable type.
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 toprintf
to make the type always correct:printf("%llu", static_cast<unsigned long long>(value));
I'm sure other people will tell you to use BOOST. So in the interest of providing a solution that is not dependent on BOOST:
I have run into the same problem so often that I gave up and wrote my own helper macros that feed into %s instead of any brand of
%llu
or%lu
or whatever. I also found it helpful for helping maintain a sane format string design, and for providing better (and more consistent) hex and pointer printouts. There are two caveats:You can't easily combine extra formatting parameters (left/right justification, padding, etc) -- but then you can't really do that with the
LU
macro either.this approach does add additional overhead to the task for formatting and printing strings. However, I write performance-critical apps and I haven't noticed it being an issue except in Microsoft's Visual C++ debug builds (which take about 200x longer to allocate and free heap memory than normal because of all the internal validation and corruption checks).
Here's a comparison:
vs.
To make it work, I used a set of macros and templates like this:
My string formatting functions are based on the now-preferred method of formatting directly into a std::string, which looks something like this: