Code Yarns ‍👨‍💻
Tech BlogPersonal Blog

Integer types in C++

📅 2015-Oct-12 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ cstdint, integer ⬩ 📚 Archive

Traditional programmers are familiar with int, 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 cstdlib.

Types of integers

C++ provides three types of fixed width integer types:

List of the signed and unsigned integer types is:




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:

#include <cstdint>
#include <iostream>

int main()
    std::cout << "Precise" << std::endl;

    std::cout << sizeof(int8_t  ) << std::endl;
    std::cout << sizeof(int16_t ) << std::endl;
    std::cout << sizeof(int32_t ) << std::endl;
    std::cout << sizeof(int64_t ) << std::endl;
    std::cout << sizeof(uint8_t ) << std::endl;
    std::cout << sizeof(uint16_t) << std::endl;
    std::cout << sizeof(uint32_t) << std::endl;
    std::cout << sizeof(uint64_t) << std::endl;

    std::cout << "Least" << std::endl;

    std::cout << sizeof(int_least8_t  ) << std::endl;
    std::cout << sizeof(int_least16_t ) << std::endl;
    std::cout << sizeof(int_least32_t ) << std::endl;
    std::cout << sizeof(int_least64_t ) << std::endl;
    std::cout << sizeof(uint_least8_t ) << std::endl;
    std::cout << sizeof(uint_least16_t) << std::endl;
    std::cout << sizeof(uint_least32_t) << std::endl;
    std::cout << sizeof(uint_least64_t) << std::endl;

    std::cout << "Fast" << std::endl;
    std::cout << sizeof(int_fast8_t  ) << std::endl;
    std::cout << sizeof(int_fast16_t ) << std::endl;
    std::cout << sizeof(int_fast32_t ) << std::endl;
    std::cout << sizeof(int_fast64_t ) << std::endl;
    std::cout << sizeof(uint_fast8_t ) << std::endl;
    std::cout << sizeof(uint_fast16_t) << std::endl;
    std::cout << sizeof(uint_fast32_t) << std::endl;
    std::cout << sizeof(uint_fast64_t) << std::endl;

    return 0;

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;
typedef int         int_fast16_t;
typedef int         int_fast32_t;
typedef long long int       int_fast64_t;

Tried with: GCC 5.1, Ubuntu 14.04 and x86_64 Intel CPU