Data Types
Every value in C++ has a type that decides how much memory it uses, what range of values it can hold, and which operations make sense. In this lesson you'll meet the full set of fundamental types, learn how big each one is, and avoid the classic traps of overflow and floating-point rounding.
Learn Data Types in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Think of types as differently sized buckets . A char is a thimble (1 byte) that holds a single drop. An int is a coffee mug (4 bytes). A long long is a bucket (8 bytes) that holds far more. A double is also a bucket but it's built to hold decimals precisely. Pour too much into a bucket and it doesn't just spill on the floor — it wraps around to the bottom , which is exactly what integer overflow does. Choosing the right-sized bucket up front prevents nasty surprises.
The C++ standard only guarantees minimum sizes; these are the common sizes on a 64-bit desktop. Use sizeof to check on your own machine.
1. The Fundamental Types in Action
Let's declare one of each and print it. Notice char uses single quotes, bool prints as 1 or 0 , and the f suffix on a float literal and the LL suffix on a long long literal pin the value to that exact type.
2. Measuring Size & Range
sizeof tells you how many bytes a type occupies, and the and headers expose each type's minimum and maximum value. Knowing the range matters because a value that exceeds it doesn't error — it silently wraps.
3. Overflow: When a Bucket Runs Out
Add 1 to the largest possible int and it wraps around to the most negative value. For signed integers this is actually undefined behavior — the compiler is free to do anything — so never rely on it. For unsigned integers the wrap is well-defined and predictable.
4. The Floating-Point Trap
Decimals like 0.1 can't be stored exactly in binary, so arithmetic introduces tiny rounding errors. cout hides them by rounding to 6 digits, but they're really there. The rule: never compare two doubles with == . Instead check that their difference is smaller than a tiny tolerance (an "epsilon").
5. auto & Literal Suffixes
auto lets the compiler deduce a variable's type from its initializer — with zero runtime cost. The type it picks depends on the literal: 10 is an int , 2.5 is a double , and suffixes like LL , u , and f nudge it toward a specific type.
Now you try. Fill in the blanks below with the right type or value:
These lines compute a percentage and print it, but they're scrambled. Put them in the correct order so the program compiles and prints Pass rate: 75% .
Why: the must come before main . Inside main , the two int variables are declared first, then percent uses them — and the 100.0 forces double division so we get 75 , not integer-truncated 0 . The print and return 0; come last, and the closing brace ends the function.
Predict the output before revealing each answer.
3 3.5 — 7 / 2 is integer division (remainder dropped), but 7.0 / 2 is double division.
2 — a bool promotes to int in arithmetic, so true + true is 1 + 1 .
4294967295 — unsigned subtraction wraps around to the maximum value rather than going negative.
Pick the right type for each value, and remember to force double division when converting bytes to megabytes. Run it and match the expected output in the comments.
Practice quiz
Which type is guaranteed to be at least 64 bits for very large whole numbers?
- int
- short
- long long
- byte
Answer: long long. long long is at least 64 bits, holding values up to about 9.2 quintillion.
What does sizeof actually return?
- The value of a variable
- The number of bytes a type occupies
- The number of bits
- The maximum value of a type
Answer: The number of bytes a type occupies. sizeof gives the number of bytes a type or object occupies, as a size_t.
What happens when you add 1 to the maximum value of a signed int?
- It stays at the maximum
- It is undefined behavior (typically wraps to the minimum)
- It throws an exception
- It becomes 0
Answer: It is undefined behavior (typically wraps to the minimum). Signed integer overflow is undefined behavior; in practice it often wraps to the most negative value.
Why should you never compare two doubles with == ?
- == is too slow
- Binary rounding means they may differ slightly
- doubles cannot be compared at all
- == only works on ints
Answer: Binary rounding means they may differ slightly. Values like 0.1 have no exact binary form, so tiny rounding errors make == unreliable; compare against an epsilon.
What does an unsigned int print for (0u - 1)?
- -1
- 0
- 4294967295
- It throws an error
Answer: 4294967295. Unsigned subtraction wraps around cleanly to the maximum value, 4294967295.
What type does 'auto big = 5000000000LL;' deduce?
- int
- double
- long long
- unsigned
Answer: long long. The LL suffix pins the literal to long long, so auto deduces long long.
What is the typical size of a double on a 64-bit desktop?
- 2 bytes
- 4 bytes
- 8 bytes
- 16 bytes
Answer: 8 bytes. double is typically 8 bytes (and int is typically 4).
How much runtime cost does 'auto' add compared to writing the type by hand?
- A small constant cost
- Zero — it is resolved at compile time
- It doubles compile time only
- It allocates extra memory
Answer: Zero — it is resolved at compile time. auto is deduced at compile time and produces identical machine code — zero runtime cost.
What does cout print for (7 / 2) followed by (7.0 / 2)?
- 3.5 and 3.5
- 3 and 3.5
- 3 and 3
- 4 and 3.5
Answer: 3 and 3.5. 7 / 2 is integer division (3); 7.0 / 2 is double division (3.5).
How can you store a value like 3000000000 without silent overflow?
- Use int
- Use char
- Use long long
- Use bool
Answer: Use long long. 3000000000 exceeds int's ~2.1 billion range; use long long for large values.