Traditional programmers are familiar with
long and such integer types. These are known to have different sizes on different systems.
However, a lot of code requires integer types to be exactly a certain size or of at least a certain size. In such situations, it is a good idea to use the fixed width integer types provided by C++ through the header file
Types of integers
C++ provides three types of fixed width integer types:
- Integer of precisely the size you specify (Ex:
- Smallest integer whose size is at least the size you specify (Ex:
- Fastest integer whose size is at least the size you specify (Ex:
List of the signed and unsigned integer types is:
int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t int_least8_t int_least16_t int_least32_t int_least64_t uint_least8_t uint_least16_t uint_least32_t uint_least64_t int_fast8_t int_fast16_t int_fast32_t int_fast64_t uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t
Why these types?
When we specify that we want an integer to have exactly 32 bits, say
int32_t, that may not be supported on certain exotic systems. Assume a computer which supports only 34-bit and 68-bit integers. That system cannot provide a 32 bit integer. Code which uses
int32_t will not compile. This is good because the programmer who used
int32_t might have been assuming the type to have exactly 32 bits, for example, if he is looping over the 32 bits to compute something. Such code should fail, else it would be a bug.
Now the use of a precise width type, like
int32_t, provides the reason for the other two types of integers: smallest and fastest.
The smallest integer type, say
int_least32_t, should be used when our code requires to store values that need at least 32 bits, but our first priority is space and not speed of computation. For example, assume that the exotic system described above does 68-bit integer addition faster than 34-bit addition. In such a case, when we use
int_least32_t, we are asking it use the 34-bit type, foregoing speed for space.
The fastest integer type, say
int_fast32_t, should be used when our code requires to store values that need at least 32 bits, but our first priority is speed and not space. For example, in the exotic system described above when we use
int_fast32_t, that system’s compiler will use the 68-bit type, providing the fastest integer addition, but by increasing space occupied by our program.
On x86_64 Linux
I now come back from a world of exotic computers to the common 64-bit x86_64 Intel processor system I’m using. On GCC C++ compiler in Linux, I found that the smallest types (like
int_least32_t) were of the same size as the precise type (like
int32_t). No surprises there cause x86_64 has integers of size 8, 16, 32 and 64.
You will get a surprise if you use the fast types though! Except for the 8-bit fast types, the rest are all mapped to 64-bit signed and unsigned integers for speed. So, a
int_fast16_t is mapped to a 64-bit signed integer.
You can print out the sizes of all the fixed width integer types, by compiling and running a simple program, I have shared here.
Another method is to look at the source code. On my x86_64 Linux with GCC 5, the
cstdint trail leads to
/usr/include/stdint.h, where I find these definitions for the fast signed types:
/* Fast types. */ /* Signed. */ typedef signed char int_fast8_t; #if __WORDSIZE == 64 typedef long int int_fast16_t; typedef long int int_fast32_t; typedef long int int_fast64_t; #else typedef int int_fast16_t; typedef int int_fast32_t; __extension__ typedef long long int int_fast64_t; #endif
Tried with: GCC 5.1, Ubuntu 14.04 and x86_64 Intel CPU