LEARNING · STAGE 00 · PROGRAMMING BASICS

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: float and double, how they differ
  • bool — the type for true/false
  • char — the type for a single character, and how it differs from text
  • std::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.

main.cppC++
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.

main.cppC++
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:

main.cppC++
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>.

main.cppC++
#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.

Step 1 — only intC++
int hp = 100;
std::cout << "HP: " << hp << "\n";

Familiar from the previous lesson — one variable, one output.

Step 2 — added doubleC++
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.

Step 3 — added boolC++
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.

Step 4 — added char and std::stringC++
#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

TypeStoresExampleWhen to Use
inta whole numberint hp = 100;counts, quantities, HP, indices — anything that cannot be fractional
doublea fractional number (default)double multiplier = 1.5;multipliers, coordinates, money with cents — fractional values by default
floata fractional number, less precision and memoryfloat multiplier = 1.5f;same as double, but when memory savings matter (for example, thousands of similar values)
booltrue or falsebool isAlive = true;yes/no states: alive/dead, on/off, found/not found
charone character (single quotes)char grade = 'A';exactly one character: a rank letter, a delimiter, a key code
std::stringtext 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.

Worse — everything in int, meaning hidden in commentsC++
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.

Better — the type matches the value's meaningC++
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.

Best of all — the output is also readable without contextC++
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; to false and output the value via std::cout — you will see that C++ prints 1 for true and 0 for false, not the word "true".
  • Change 1.5 to 1.5f on a variable of type float — 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 type int with an implementation-defined value. The compiler may issue a warning and accept an ordinary assignment with conversion to char; 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.

Double quotes instead of single quotes for a char
char grade = "A";   // double quotes are a string, not a character
console (illustration)
g++ main.cpp -o main main.cpp:4:18: error: invalid conversion from 'const char*' to 'char' [-fpermissive] 4 | char grade = "A"; | ^~~ | | | const char* Compilation failed.

"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 without #include <string>
std::string name = "Ada";   // #include <string> is missing above
console (illustration)
g++ main.cpp -o main main.cpp:6:10: error: 'string' is not a member of 'std' 6 | std::string name = "Ada"; | ^~~~~~ Compilation failed.

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.)

Fractional value lost when stored into an int
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.

Choose the type
Which type best suits the value "the first letter of a player's surname"?
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.

Predict the result
What will this program print — the word "true" or something else?
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).

Hidden bug
The compiler will accept this line without a single error. What will 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.

★ Include <string>, declare a std::string with your name (text), and output a greeting like "Hello, Ada!" via std::cout, using that variable.

★★★ 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.

14Terms

TermMeaning
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 literala single character in single quotes, for example 'A' — a value of type char
String literaltext in double quotes, for example "Ada" — the source value for std::string
Type suffixa 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::cout will output for a bool value — not the word, but 0 or 1.
  • You can explain why assigning a fractional value to an int variable 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 often float) — fractional numbers; double is the default choice in this course.
  • bool — true/false, printed as 1/0 via std::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 int truncates 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.

🎮 How Does This Relate to Unreal Engine?

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:

Player.h (Unreal C++, example)C++
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+.