Fundamental Data Types
Up to now, every variable in the course has been of type int — whole numbers. But a character's health with a fractional damage multiplier, an "alive/dead" state, a grade letter, a player's name — these are not whole numbers. This lesson covers the remaining basic C++ types: float/double, bool, char, and std::string, and how to choose the right one.
01What You Will Learn
- Fractional numbers:
floatanddouble, how they differ bool— the type for true/falsechar— the type for a single character, and how it differs from textstd::string— the type for text of arbitrary length- How to choose a type for a specific value
02Technically, This Lesson Is Not Strictly Required
You could store absolutely everything as int — health, damage multiplier, "is the character alive" state, rank, name. Health, 100 — fits perfectly. Damage multiplier, 1.5? int only stores whole numbers — the fractional part simply disappears if you try to shove something fractional into it (a detailed breakdown is in the next lesson on operators; for now it is enough to know this trap exists). The "is the character alive" state is not a number at all, but one of two options: technically it would fit as 0 or 1, but nothing prevents you from accidentally writing 42 there. A rank letter is a single character, not a quantity. A player's name is text of unknown length. None of these four cases is honestly described by int — hence this whole lesson: C++ has a dedicated type for each of them, one that does not merely "also compile," but refuses to let you write nonsense into it.
03float and double — Fractional Numbers
For a damage multiplier of 1.5 you need a type that honestly stores the fractional part — C++ has two such types: float and double. The difference between them is not about "what is allowed and what is not," but about size and precision: double occupies 8 bytes of memory and stores values more precisely, while float occupies 4 bytes and is coarser. In this course, double is the default choice; float will be useful later, when an Unreal project has thousands of such variables and the memory savings start to actually matter.
double damageMultiplier = 1.5; // a literal without a suffix is double by default
float lightMultiplier = 1.5f; // the f suffix means explicitly float
A fractional literal like 1.5 without a suffix is considered double by the compiler by default; to get an actual float, the suffix f is appended to the number. For now, double will be used almost everywhere in this course — that is sufficient.
04bool — True or False
"Is the character alive" is a question with only two possible answers, and storing it in an int would mean allowing values like 2, 100, or −7 to be written there — even though none of those numbers means anything for "alive/dead." bool closes exactly that hole: it stores exactly one of two values, true or false, and nothing else fits into it. It suits any yes/no state: on/off, alive/dead, found/not found.
bool isAlive = true;
bool hasKey = false;
bool becomes a truly working tool in the next lessons: the result of a comparison (x > 5) is a bool, and conditions (if) work precisely with it. Here it is enough to know that such a type exists and what it stores.
05char — a Single Character
A rank letter ("A", "B", "F") is not text of arbitrary length, but exactly one character, and for that case reaching for int or std::string is excessive. char is the type for exactly this: it stores exactly one character, no more and no less. It also has its own distinct notation — single quotes, as opposed to text in double quotes, which already appeared in the first lesson:
char grade = 'A'; // one character — single quotes
std::string name = "Ada"; // text — double quotes, a different type
'A' and "A" are not the same thing in C++: the first is a char (one character), the second is text consisting of one character (type const char[2]: the character and a terminating null; std::string can be created from this literal — arrays are covered separately in Stage 02). Confusing the two is a common beginner mistake; see the "Common Mistakes" section below.
06std::string — Text
A player's name does not fit into a char — it usually has more than one letter, and you do not know in advance how many. You need a type that adapts itself to the length of the text — std::string, also from the standard library (like std::cout), and also requiring its own #include <string>.
#include <string>
std::string playerName = "Ada";
std::cout << "Hello, " << playerName << "!";
You already output a quoted string in the very first lesson ("Hello, C++!\n") — back then it was a string literal used directly inside std::cout, without a variable. Now the same value can be stored in a std::string variable and used by name — exactly as with int or double.
07Building Character Stats Step by Step
This is a continuation of the character program from the previous lesson: there the first variable appeared, hp (short for playerHealth — see the previous lesson). Below is the same program, gaining one more variable of a new type at each step. These are not five different examples, but one and the same main() gradually accumulating details — much like real development looks: first the simplest version, then fields are added to it one by one.
int hp = 100;
std::cout << "HP: " << hp << "\n";
Familiar from the previous lesson — one variable, one output.
int hp = 100;
double damageMultiplier = 1.5;
std::cout << "HP: " << hp << ", Multiplier: " << damageMultiplier << "\n";
The damage multiplier is fractional — int does not fit here (see the "Live Debugging" section below), so it is a double.
int hp = 100;
double damageMultiplier = 1.5;
bool isAlive = true;
std::cout << "HP: " << hp << ", Multiplier: " << damageMultiplier
<< ", Alive: " << isAlive << "\n";
"Is the character alive" is neither a number nor a fraction, but one of two options, hence bool.
#include <string>
int hp = 100;
double damageMultiplier = 1.5;
bool isAlive = true;
char grade = 'A';
std::string playerName = "Ada";
std::cout << playerName << " — HP: " << hp
<< ", Multiplier: " << damageMultiplier
<< ", Alive: " << isAlive
<< ", Grade: " << grade << "\n";
The final version uses all five types from this lesson in a single program, each for its own kind of value. This same construction will be useful in task 3 below.
08Types — Table
| Type | Stores | Example | When to Use |
|---|---|---|---|
int | a whole number | int hp = 100; | counts, quantities, HP, indices — anything that cannot be fractional |
double | a fractional number (default) | double multiplier = 1.5; | multipliers, coordinates, money with cents — fractional values by default |
float | a fractional number, less precision and memory | float multiplier = 1.5f; | same as double, but when memory savings matter (for example, thousands of similar values) |
bool | true or false | bool isAlive = true; | yes/no states: alive/dead, on/off, found/not found |
char | one character (single quotes) | char grade = 'A'; | exactly one character: a rank letter, a delimiter, a key code |
std::string | text of arbitrary length (double quotes) | std::string name = "Ada"; | text of arbitrary length: a name, a message, an item name |
09Worse → Better: a Type That Describes the Meaning
The task is to store "is the character alive" and a "letter grade." Both values technically fit into an int — but that does not mean it should be done that way.
int isAlive = 1; // intended as true/false
int grade = 65; // intended as the character 'A' (65 is its ASCII code)
std::cout << isAlive << " " << grade;
It compiles and "works" — it will print 1 65. But nothing stops the int type from being assigned isAlive = 42; — the compiler sees nothing wrong here, even though such a value is meaningless for "alive/dead" by its meaning. The variable's meaning rests solely on the comment, and comments are not checked by anyone.
bool isAlive = true;
char grade = 'A';
std::cout << isAlive << " " << grade;
Same result semantically (prints 1 A — bool is printed as 0/1, see the "Try Changing It" section below), but now the type itself prevents assigning anything other than true/false to isAlive, or anything longer than one character to grade. The comment about the value's meaning is no longer needed — the type already expresses it.
bool isAlive = true;
char grade = 'A';
std::cout << "Alive: " << isAlive << ", Grade: " << grade << "\n";
Now even the output 1 instead of the word "true" is not confusing — next to it stands the label "Alive:", explaining what that number is.
10Try Changing It
- Change
bool isAlive = true;tofalseand output the value viastd::cout— you will see that C++ prints1for true and0for false, not the word "true". - Change
1.5to1.5fon a variable of typefloat— the behavior will not change, but this makes it clearly visible that it is a float literal. - Try writing
char grade = 'AB';(two characters in single quotes) — this is a multi-character literal of typeintwith an implementation-defined value. The compiler may issue a warning and accept an ordinary assignment with conversion tochar; a guaranteed compilation error is not present here. For a single character, use'A'.
11Live Debugging: Common Mistakes
The exact error text depends on the compiler and its version — below is a typical g++-style appearance.
char grade = "A"; // double quotes are a string, not a character
"A" has type const char[2]; in this expression the array is converted to const char* (hence the type in the diagnostic), not to a single character — the types do not match, and the compiler refuses to implicitly convert one into the other. A char needs single quotes: 'A'.
std::string name = "Ada"; // #include <string> is missing above
Exactly the same as std::cout without #include <iostream> in the first lesson. (On some compilers the code may unexpectedly compile even without an explicit #include <string>, because some other header pulled it in accidentally — do not rely on this; the behavior is not guaranteed by the standard.)
int score = 9.99; // the fractional part is silently discarded, score becomes 9
This is not a compilation error — the program will build successfully (possibly with a warning about loss of precision). It is more dangerous than a compilation error precisely because nothing "crashes" — the code silently does something other than what was intended. If a value is fractional, the variable's type must be double (or float), not int.
12Check Yourself
Three questions: choosing a type by the value's meaning, predicting non-obvious output, and a re-encounter with the "hidden bug" from the live debugging section.
Show explanation
char — exactly one character, not text of arbitrary length (that would be std::string). int does not fit here — a letter is not a number, and bool stores only two states.
bool hasKey = true;
std::cout << hasKey;Show explanation
It will print 1, not the word "true". std::cout outputs a bool as 1/0 by default — this applies to all values of type bool; the word appears only if you explicitly request it with a separate stream setting (beyond the scope of this lesson).
score be equal to?int score = 9.99;Show explanation
score becomes equal to 9 — the fractional part is silently discarded when stored into an int (see §11); no rounding to the nearest integer occurs. The compiler is not required to treat this as an error: technically such a conversion is allowed by the language (a warning may be issued, but not an error) — which is exactly why this bug is easy to miss, unlike errors such as double quotes on a char, which compilation rejects immediately.
13Practice
★ Declare three variables: bool (for example, isAlive), char (for example, grade), and double (for example, damageMultiplier) — each with a meaningful name and value. Output all three via std::cout.
Three separate declarations, each of its own type — bool, char (single quotes!), and double — and one or three std::cout statements outputting all three.
Solution: bool isAlive = true; char grade = 'A'; double damageMultiplier = 1.5; — then std::cout << isAlive << grade << damageMultiplier; (either in one statement or in three separate ones).
★ Include <string>, declare a std::string with your name (text), and output a greeting like "Hello, Ada!" via std::cout, using that variable.
#include <string> is needed as a separate line at the top of the file, before int main() — without it std::string does not exist for the compiler (§06).
Solution: #include <string> at the top, std::string playerName = "Ada";, then std::cout << "Hello, " << playerName << "!";
★★★ Build a single "character stats" program using all five types from this lesson: int (for example, hp), double (for example, damageMultiplier), bool (for example, isAlive), char (for example, grade), and std::string (for example, playerName). Output all five values on one line via std::cout, as in step 4 of the "Building Character Stats" section above.
Five separate declarations, one of each type — the order of declaration does not matter; what matters is that each is initialized with a value of an appropriate kind (whole number, fractional, true/false, a character in single quotes, text in double quotes).
The output is a single std::cout chain with five << in a row, as in step 4 of the "Building Character Stats" section — each variable must actually appear after <<, not just exist somewhere above in the code.
Solution: int hp = 100; double damageMultiplier = 1.5; bool isAlive = true; char grade = 'A'; std::string playerName = "Ada"; — then output all five via a single std::cout using <<, as in step 4 of the example above.
14Terms
| Term | Meaning |
|---|---|
| Fractional number (floating-point) | a number with a fractional part — represented by the types double/float |
| Logical value (boolean) | the value true or false — the type bool |
| Character literal | a single character in single quotes, for example 'A' — a value of type char |
| String literal | text in double quotes, for example "Ada" — the source value for std::string |
| Type suffix | a letter after a numeric literal specifying its type, for example f in 1.5f (float) |
15What You Can Do Now
Before this lesson, the only tool was int. Now you have a choice — and an understanding of what justifies it:
- For a specific value (quantity, yes/no state, one character, text) you can choose an appropriate type instead of shoving everything into
int"because it compiles." - You can explain the difference between
'A'and"A"and predict how the compiler will react if the quotes are swapped by mistake. - You can predict exactly what
std::coutwill output for aboolvalue — not the word, but 0 or 1. - You can explain why assigning a fractional value to an
intvariable does not cause a compilation error, but leads to silent data loss. - You can build a single program using several different types simultaneously, each for its own kind of value, not for the number of lines.
16Summary
double(and less oftenfloat) — fractional numbers;doubleis the default choice in this course.bool—true/false, printed as1/0viastd::cout.char— one character, single quotes ('A'), not to be confused with a string in double quotes.std::string— text of arbitrary length, double quotes, requires#include <string>.- Storing a fractional value into an
inttruncates the fractional part without a compilation error — a source of silent bugs.
All five types are in place — but for now you can only declare and output values with them. The next lesson adds operators: arithmetic, comparison, and logic, without which the types remain mere containers for numbers and text.
These types will be used in Unreal C++ in exactly the same way — just under different names. Unreal prefers its own fixed-size types such as int32 instead of a bare int (a guarantee that the variable occupies exactly 32 bits on any platform — int itself formally does not guarantee this), and instead of std::string it has its own type FString (for the same reason the engine has its own memory and build system). The principle "choose the type to match the value" carries over unchanged:
int32 Health = 100; // instead of int
float DamageMultiplier = 1.5f; // instead of double — Unreal more often uses float
bool bIsAlive = true; // bool remains bool, but with the b prefix
FString PlayerName = "Ada"; // instead of std::string
Note: bool variables in Unreal are conventionally named with the b prefix (bIsAlive, not isAlive) — this is an engine naming convention, not a C++ language requirement. Details about FString and other Unreal text types — in Stage 07+.