LEARNING · STAGE 00 · PROGRAMMING BASICS

Variables, Identifiers, and Types

You already wrote int x = 10; and x = x + 5; in the previous lesson — and the code worked, even though you most likely didn't ask yourself what x actually is here, why int comes before it, and why the second line looks shorter than the first. Time to ask. This is also where the program begins that will grow with you through all the following Stage 00 lessons — a game character card.

01What you will learn

  • What actually happens in memory when int x = 10; is executed
  • Which names C++ allows for variables, and which it doesn't
  • What a type is and why a variable needs one at all
  • Why int x = 10; and x = x + 5; are actually two different kinds of instructions, not one

02What happens when the computer sees int x = 10;

The computer does not "understand" code the way you do — it executes it literally, step by step, without inferring anything. Here is what actually happens when execution reaches the line int x = 10;: somewhere in memory a free spot is found that fits one integer, that spot is given the name x, and the value 10 is immediately placed there. That place in memory, accessible by name, is a variable.

Later, when x appears in the code again — for example in x = x + 5; — the program does not create a new place in memory, but accesses the same one, by the same name. Let's look at all three lines in a row and at what happens to memory at each step:

What's in memory, step by stepC++
int x = 10;
// memory: [ x: 10 ]  — the cell is created, immediately with a value

x = x + 5;
// step 1: read the current value of x → 10
// step 2: evaluate the expression 10 + 5 → 15
// step 3: place 15 back into the same cell x
// memory: [ x: 15 ]  — same cell, different value

std::cout << x;
// read the current value of cell x → output 15
// memory: [ x: 15 ]  — reading does not change the value

Across all three lines, x had exactly one address in memory. The three instructions did not create three variables — they accessed the same cell by name three times. The value inside changed, but the place itself (and the name by which it is found) did not. This is what distinguishes a variable from a constant value.

03How to name a variable so the compiler agrees

A variable name (like a function name — for example, main) is called an identifier. If C++ allowed absolutely any text as a name, problems would arise immediately: spaces inside a name would make it unclear where the name ends and where the next part of the code begins; a name starting with a digit would be confused by the compiler with a number; a word like return used as a variable name would collide with the same word that already has a fixed meaning in the language. From this grow the actual C++ rules:

  • you can use Latin letters, digits, and the underscore character _;
  • the first character cannot be a digit (2ndPlayer is an error, secondPlayer is fine);
  • you cannot use reserved words of the language — return, int, if, and similar are already taken;
  • C++ is case-sensitive: health, Health, and HEALTH are three different identifiers;
  • spaces inside a name are forbidden.

The compiler checks all of this itself and will simply refuse to build the code if any rule is broken. But there is a question the compiler does not check at all, and you pay for it yourself: syntactically, x is no worse than playerHealth — the compiler doesn't care. But a person who opens this code in a month (including you yourself) will get nothing from x about what is stored there, while playerHealth will tell them immediately, for the same amount of typing effort.

04Worse → better: variable names

The task is the same — store the player's health points and the number of login attempts. The first of these two variables — playerHealth — is not just an example: it starts the character program that will grow from lesson to lesson until the very end of Stage 00.

Worse — compiles, but says nothing about the meaningC++
int a = 100;
int b = 0;
std::cout << "HP: " << a << ", Attempts: " << b;

Syntactically everything is correct. But remove the neighboring line with std::cout for a second — what are a and b? There is nowhere to guess from. And if there are twenty variables, you will have to guess twenty times in a row.

Better — the name says what's insideC++
int playerHealth = 100;
int attempts = 0;
std::cout << "HP: " << playerHealth << ", Attempts: " << attempts;

Now the std::cout line is no longer needed at all to understand the meaning — playerHealth and attempts speak for themselves.

Best — the name removes an even subtler ambiguityC++
int playerHealth = 100;
int loginAttempts = 0;   // precisely login attempts, not, for example, attack attempts
std::cout << "HP: " << playerHealth << ", Attempts: " << loginAttempts;

attempts by itself is not unambiguous — attempts of what exactly? In a small program it doesn't matter, but as the code grows, such small clarifications save time for everyone who reads it later.

One caveat for the future: later in the course the same variable will be called more briefly — hp. This does not contradict what was just said: hp is a generally accepted abbreviation in game development; its meaning is clear from context almost always, not only inside a single program. Here we deliberately choose the full name because the abbreviation has not been introduced yet — we are not stumbling onto a short name out of ignorance, but choosing it later consciously.

05Type — why the compiler needs more than just "a variable"

Without the word int, int x = 10; is meaningless to the compiler — "a variable, but a variable of what?", a question without an answer. The word int itself before the name is the answer: it is a type, an indication of what kind of value will be stored here and how much memory to allocate for it. int means "integer". The compiler uses this information constantly: how many bytes to allocate for the value, what can be done with it (numbers can be added, while text, looking ahead, cannot be so simply), and it will not let you accidentally put into the variable something that does not match the type.

Besides int, C++ has types for fractional numbers, for true/false, for a single character, for text — that is the entire topic of the next lesson. Here it is enough to take away one fact: every variable has a type; it is chosen at declaration and determines what can be done with the value later.

06int x = 10; and x = x + 5; — why these are different things

Both lines already appeared in the previous lesson without names. Let's look at the difference more carefully:

main.cppC++
int x = 10;   // initialization
x = x + 5;    // assignment

In the first line the word int appears — the variable is created right here, for the first time, and immediately receives a value. This is called initialization: the variable and its first value appear simultaneously, in one instruction.

In the second line the word int is absent — and it cannot be: x already exists, so it does not need to be declared again and cannot be. This is assignment: changing the value of an already existing variable. The instruction takes the current value of x, computes the new one (15), and places it back into the same variable.

A variable can be declared without initialization — then it has no assigned value at first, and it will have to be assigned later with a separate instruction:

Declaration without initializationC++
int attempts;     // declaration WITHOUT initialization — no value yet
attempts = 0;      // assignment — only now does attempts get a value
attempts = 1;       // another assignment — the value changes

Three separate instructions: one declares the variable, the other two assign it values in turn. There is a catch here: while the variable is declared but the value has not yet been assigned, reading it (for example, outputting it via std::cout) is already syntactically possible, but you will get undefined garbage left in memory from something else. A practical rule: if the initial value is known in advance — initialize immediately at declaration, do not postpone it without necessity.

07Comments — notes the compiler does not see

The comments // initialization and // assignment in the example above already showed what this looks like. A comment is text in code that the compiler completely ignores, but a person reads. Two ways to write one:

SyntaxWhat it comments
// texteverything to the end of the line
/* text */everything between /* and */; can span multiple lines

A useful comment does not retell what is already visible from the code (x = x + 5; // add 5 to x — useless, it is already readable), but explains what is not visible: why exactly this number, why exactly this way and not another. The more complex the program becomes, the more this pays off.

08Try changing it

  • In the attempts example, replace int attempts; with int attempts = 0; and remove the first assignment instruction — the result will not change, but now it is initialization, not a subsequent assignment.
  • Try declaring a variable named int — the compiler will refuse; it is a reserved word.
  • Declare a variable with a name starting with a digit (for example int 2x = 5;) — also a compilation error.

09Live debugging: common mistakes

The exact error text depends on the compiler and its version — below is the typical appearance in the style of g++.

Identifier starts with a digit
int 2ndTry = 0;   // an identifier cannot start with a digit
console (illustration)
g++ main.cpp -o main main.cpp:4:9: error: invalid suffix "ndTry" on integer constant 4 | int 2ndTry = 0; | ^~~~~~ Compilation failed.

The compiler sees 2 as the beginning of a number, not a name, and tries to parse 2ndTry as a number with a strange suffix — hence the not entirely obvious wording of the error. The fix is to rearrange: secondTry or try2.

A reserved word was used
int return = 5;   // return is a keyword and cannot be a name
console (illustration)
g++ main.cpp -o main main.cpp:4:9: error: expected unqualified-id before 'return' 4 | int return = 5; | ^~~~~~ Compilation failed.

The same applies to int, if, while, and other keywords — each has a fixed meaning in the language; you cannot make a variable name out of them.

Reading a variable before assigning a value
int score;              // declared, but not initialized
std::cout << score;   // reading "garbage" from memory — compiles, but is unpredictable

This error will not appear in the compiler console — the program will successfully build and run, but will output an unpredictable value (it may be 0, or it may be random "garbage"). Compilers often warn about this separately (a warning, not an error), and such a warning is not worth ignoring.

Re-declaring a variable with the same name
int score = 0;
int score = 10;   // not assignment, but re-declaration — an error
console (illustration)
g++ main.cpp -o main main.cpp:5:9: error: redefinition of 'int score' 5 | int score = 10; | ^~~~~ main.cpp:4:9: note: 'int score' previously declared here 4 | int score = 0; | ^~~~~ Compilation failed.

One identifier cannot have two declarations in the same scope (more on this in the last lesson of Stage 00). To simply change the value, you do not write the word int before the name again: score = 10; is assignment, not a new declaration.

10Check yourself

Three questions on different things: admissibility of a name, the difference between initialization and assignment, and predicting a non-obvious result. For each question, it is worth first trying to cover the answer with your hand and think for yourself — the answer is not going anywhere.

Classification
Which of these names will the compiler accept as an identifier?
Show explanation

player_health — letters and underscore are allowed, and the name does not start with a digit. The other three will be rejected: 2ndPlayer starts with a digit (the compiler will try to read "2" as a number), int is a reserved word of the language, and Player Health contains a space — the compiler will see two tokens instead of one identifier.

Initialization or assignment?
In this fragment — which line is initialization, and not assignment?
int score = 0;
score = 5;
score = score + 1;
Show explanation

int score = 0; — initialization: the word int is present, the variable is created and immediately receives a value in one instruction. Both following lines are assignments: int is no longer written (the variable exists); only the value of the already existing memory cell changes.

Predict the result
What will the first line output — is it necessarily 0?
int score;
std::cout << score;
score = 42;
Show explanation

Undefined value. score is declared without initialization — before the line score = 42;, its memory cell contains whatever happened to be there by chance (see §09) — the compiler is not obliged to zero the memory itself. It compiles without error, but the result of the first output is unpredictable.

11Practice

★ Replace the meaningless name a with a meaningful one (for example, playerHealth), initialize it with the value 100, and output it via std::cout in the format "HP: 100".

★★ Declare a variable attempts without an initial value, then assign it 0 with a separate instruction, then change it to 1 with another separate instruction, and output the final value via std::cout.

12Terms

TermMeans
Variablea named area of memory for storing a value, accessible by name
Identifierthe name of a variable, function, or other entity — according to the strict syntactic rules of C++
Typean indication of what kind of value a variable stores and what can be done with it
Initializationthe first value of a variable, set in the same instruction where the variable is declared
Assignmentchanging the value of an already existing variable with a separate instruction
Commenttext in code that is ignored by the compiler and read only by a person

13What you can do now

Before this lesson, int x = 10; just worked. Now you have a model of what stands behind each word in that line:

  • You can explain what happens in memory when int x = 10; is executed, and why a later reference to x does not create a new cell, but uses the same one.
  • You can determine whether a proposed variable name is admissible as a C++ identifier, and explain the specific reason if the compiler rejects it.
  • You can distinguish initialization from assignment in any code fragment, not only in the examples of this lesson.
  • You can predict why reading a variable before assigning a value is dangerous — and why the compiler is not obliged to point out this error explicitly.
  • You can choose a name for a new variable that speaks about its contents by itself, rather than relying on a neighboring explanatory comment or output.

14Summary

  • A variable is a named place in memory; the name does not change, but the value inside can.
  • An identifier is the name of a variable (or function): letters, digits, _, not starting with a digit, not a reserved word, case matters.
  • A meaningful name is not a requirement of syntax, but a requirement of human readability of the code.
  • A type determines what kind of value a variable stores and what can be done with it — the specific types are covered in the next lesson.
  • Initialization is the first value at declaration (int x = 10;); assignment is changing the value of an already existing variable (x = x + 5;).
  • A variable can be declared without initialization, but reading its value before the first assignment is an error.

So far, the only type has been int — but fractional numbers, true/false, and text are structured differently and stored differently. The next lesson covers this difference instead of leaving it implicit.

🎮 How does this relate to Unreal Engine?

In Unreal C++, variables are declared exactly the same way — type, name, optional initialization. The difference appears later (Stage 07+), when class member variables start being marked with the UPROPERTY() macro so that Unreal can see them in the editor and Blueprint — but the very rule "a meaningful variable name saves time when reading" works even more critically in Unreal projects, where variables number in the thousands, than in the educational examples here.