smhk

Print a 64-bit integer using 32-bit integers

To print a 64-bit unsigned integer in a portable way, ideally you would do as follows:

example_1.c
#include <stdio.h>
#include <inttypes.h>

int main()
{
    uint64_t val = 18369614221190020847;
    printf("%" PRIu64, val);
    return 0;
}

Where PRIu64 is a macro provided by inttypes.h, that typically expands to some string literal like llu. So upon compiling, the string will concatenate to form %llu, which formats an unsigned long long value in decimal:

Output (good)
18369614221190020847

However, if targeting an embedded platform with a stripped down version of libc1, such as newlib-nano, this may silently fail! While the type uint64_t may exist, and the PRIu64 macro may also exist, if the version of printf (provided by libc) does not support the %llu macro, instead of printing 18369614221190020847, it will just print the string literal %llu2:

Output (bad)
%llu

If you cannot change your version of libc, and need to print in decimal, there is no easy way around this.3

However, if you can tolerate printing in hexadecimal rather than decimal, you can seamlessly print the 64-bit unsigned integer as two 32-bit unsigned integers:

example_2.c
#include <stdio.h>
#include <inttypes.h>

int main()
{
    uint64_t val = 18369614221190020847;
    printf("0x%08" PRIx32 "%08" PRIx32, (uint32_t)(val >> 32), (uint32_t)(val));
    return 0;
}
Output (good enough)
0xfeedfacecafebeef

  1. Here are some considerations for embedded C standard libraries. ↩︎

  2. May be llu, lu, or potentially even u, depending upon your platform. ↩︎

  3. If you can switch from newlib-nano to newlib, it may be possible to use the flag --enable-newlib-io-long-long↩︎