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;
}
More at std::numeric_limits – cppreference.com.
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:
int8_t int16_t int32_t int64_t | Signed integer type with width of exactly 8, 16, 32 and 64 bits respectively with no padding bits and using 2’s complement for negative values (provided only if the implementation directly supports the type) |
int_least8_t int_least16_t int_least32_t int_least64_t | Smallest signed integer type with width of at least 8, 16, 32 and 64 bits respectively |
intmax_t | Maximum-width signed integer type |
uint8_t uint16_t uint32_t uint64_t | Unsigned integer type with width of exactly 8, 16, 32 and 64 bits respectively (provided only if the implementation directly supports the type) |
uint_least8_t uint_least16_t uint_least32_t uint_least64_t | smallest unsigned integer type with width of at least 8, 16, 32 and 64 bits respectively |
uintmax_t | maximum-width unsigned integer type |
More at Fixed width integer types (since C++11) – cppreference.com.
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
std::cout << "char is signed == " << std::numeric_limits::is_signed << std::endl;
should it be ?
It depends on your architecture.
https://godbolt.org/z/zesxh5nW9 says yes for instance. But no garantee it is true on every system.
thanks. I think what confused me is that the cout says “char” but the numeric limits says double. why is that?
Hur… sorry for the typo, Imma correct that immediatly 🙂
ok. thanks and thank you for writing those articles. I love it!