Author: Chloé Lourseyre

If I’d come up with a pop quiz about sizes in C++, most C++ developers would fail it (I know I would), because sizes in C++ are complicated.

The size of every fundamental type is not fixed, they are always implementation-defined.

Sill, the standard defines constraints on these sizes. These constraints take the form of one of these:

• A comparison of the types’ `sizeof`.
• The type’s minimum number of bits.

What is sizeof()?

One of the most widespread (and harmless) misconceptions about type sizes is that a byte holds 8 bits.

Although this is mostly true in practice, this is technically false.

A byte is actually defined as the size of a `char`. Though a `char` must have at least 8 bits, it can hold more. `sizeof(N)` returns the number of bytes of the type `N`, and every type size is expressed in terms of a `char` length. Thus, a 4-byte `int` is at least 32-bit, but you may not assume more from it (it could be 128-bit if a `char` is 32-bit).

The actual size of a byte is recorded in `CHAR_BIT`

Summary of sizes in C++

Here are all the definitions and restrictions of fundamental types’ sizes in C++:

• 1 ≡ sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long) ≤ sizeof(long long)
• 1 ≤ sizeof(bool) ≤ sizeof(long)
• sizeof(char) ≤ sizeof(wchar_t) ≤ sizeof(long)
• sizeof(float) ≤ sizeof(double) ≤ sizeof(long double)
• sizeof(N) ≡ sizeof(unsigned N) ≡ sizeof(signed N)
• A char has at least 8 bits
• A short has at least 16 bits
• A long has at least 32 bits

… and nothing more.

Fun fact: according to this definition, it is technically possible that all fundamentals have 32 bits.

Two words of wisdom

Since the sizes of the fundamental types entirely depend on the architecture, it may sometimes be hard to write consistent code.

#include <limits>

`limits` of the standard library contains the upper and lower limits of every fundamental type, and allows you to know if a given type is signed or not.

Example:

```#include <limits>
#include <iostream>

int main()
{
std::cout << "largest double == " << std::numeric_limits<double>::max() << std::endl;
std::cout << "char is signed == " << std::numeric_limits<char>::is_signed << std::endl;
}
```

Reminder: signed integer overflow is undefined behavior. Using limits helps you in preventing that from happening.

#include <cstdint>

Sometimes you may want to deal with fixed-sized types (in terms of bit) and not rely on the implementation specifics. For instance, if you implement serialization, work on very limited memory space, or develop cross-platform software, you may want to explicitly provide the bit-size of the type you’re using.

You can do so with the library `cstdint` which contains fixed-size types.

Here are a few of them:

Wrapping up

If you want to read more about type size, refer to section §6.2.8 of The C++ Langage (Bjarne Stroustrup). More broadly, you can read about types and declarations in the whole section §6 of the book.

You can also refer to Fundamental types – cppreference.com for online documentation

Thanks for reading and see you next week!

Author: Chloé Lourseyre

Categories: UFO