cprintfstdint

How do I find the width of a uint_fast32_t


I'd like to be able to portably fprintf() a uint_fast32_t as defined in stdint.h with all leading zeroes. For instance if my platform defined uint_fast32_t as a 64-bit unsigned integer, I would want to fprintf() with a format specifier like %016lX, but if it's a 32-bit unsigned integer, I would want to use %08lX.

Is there a macro like INTFAST32_BITS somewhere that I could use?

right now I'm using

#if UINT_FAST32_MAX == 0xFFFFFFFF
#    define FORMAT "08"PRIXFAST32
#elif UINT_FAST32_MAX == 0xFFFFFFFFFFFFFFFF
#    define FORMAT "016"PRIXFAST32
#endif

But this only works with uint_fast32_t that is exactly 32 or 64 bits wide, and the code is also kinda clunky and hard to read


Solution

  • You can find the size of a uint_fast32_t the same way you can find the size of any other type: by applying the sizeof operator to it. The unit of the result is the size of type char. Example:

    size_t chars_in_a_uint_fast32_t = sizeof(uint_fast32_t);
    

    But this is not sufficient for printing one with one of the printf-family functions. Undefined behavior arises in printf et. al. if any formatting directive is mismatched with the type of the corresponding argument, and the size of of uint_fast32_t is not sufficient information to make a proper match.

    This is where the formatting macros already described in your other answer come in. These provide the appropriate size modifier and conversion letter for each type and conversion. For an X conversion of uint_fast32_t, the appropriate macro is PRIXFAST32.

    You provide any flags, field width, and precision as normal. If indeed you want to use a field width that is adapted to the actual size of uint_fast32_t, then a reasonable way to do that would be to avail yourself of the option to specify that the field width is passed as an argument (of type int). Thus:

    uint_fast32_t fast;
    // ...
    printf("%0*" PRIXFAST32 "\n", (int) sizeof(fast) * 2, fast);
    

    I note, however, that this seems a little questionable, inasmuch as you are making provision for values wider than generally you should allow any value of that type to become. The printf function will not in any case print fewer digits than are required to express the value, supposing that it is indeed of the specified type, so I would be inclined to simply use a fixed field width sufficient for 32-bit integers (say 8).