c++c++11integerstdint

uint32_t vs uint_fast32_t vs uint_least32_t


I saw different types of definition of an integer in stdint.h. I'll take unsigned 32-bit integer as an example.

  1. uint32_t means clearly an unsigned integer of 32 bits. That's the one I always use.

  2. uint_fast32_t and uint_least32_t : What's the difference with uint32_t and when should I use them instead of uint32_t ?

And now, I saw uintX_t where X is 24, 40, 48 and 56. It happens in my code that I have to work with 48 and 56-bit integers. As an example, I suppose uint24_t is define as something like this :

struct uint24_t { unsigned int the_integer : 24; };

Am I right ? And, Will you suggest me to use uint48_t for my 48-bit unsigned integers or should I use the normal uint64_t ?

Thanks for your explanations.


Solution

  • what's the difference with uint32_t

    uint_fast32_t is an unsigned type of at least 32 bits that is (in some general way) the fastest such type. "fast" means that given a choice, the implementer will probably pick the size for which the architecture has arithmetic, load and store instructions. It's not the winner of any particular benchmark.

    uint_least32_t is the smallest unsigned type of at least 32 bits.

    uint32_t is a type of exactly 32 bits with no padding, if any such type exists.

    Am I right?

    No. If uint24_t exists at all then it is an integer type, not a struct. If there is no unsigned integer type of 24 bits in this implementation then it does not exist.

    Since unsigned long is required to be at least 32 bits, the only standard types that uint24_t could possibly ever be an alias for are char, unsigned char, unsigned short and unsigned int. Alternatively it could be an extended type (that is, an integer type provided by the implementation that is not any of the defined integer types in the standard).

    Will you suggest me to use uint48_t for my 48-bit unsigned integers?

    If it exists and is the size you want then you might as well use it. However, it will not exist on very many implementations, so it's only suitable for use in non-portable code. That's OK provided the reason you have to deal with exact 48-bit integers is platform-specific.

    The exact 16, 32 and 64 bit types are also technically optional, but they are required to exist if the implementation has suitable integer types. "Suitable" means not only that there is an exact N bit unsigned type with no padding bits, but also that the corresponding signed type has no padding bits and uses 2's complement representation. In practice this is so close to everywhere that you limit portability very little by using any of them. For maximum portability though you should use uint_least32_t or uint_fast32_t in preference to uint32_t. Which one depends on whether you care more about speed or size. In my experience very few people bother, since platforms that don't have a 32 bit integer type are already so weird that most people don't care whether their code runs on it or not.