Statements and Expressions
In the previous lesson you already wrote a working program with std::cout, #include and return 0; — but you didn't call the things it consists of by their proper names. This lesson introduces two terms that will be used in every topic of the course from now on without additional explanations: statement and expression.
01What you will learn
- How a statement differs from an expression
- What a code block is and what the curly braces
{ }are for - How an expression can be evaluated directly inside another statement, without an intermediate variable
- Which errors most often arise from confusing a statement with an expression
02Why it matters
Later in the course there will be conditionals (if), loops (for, while) and functions — and in the explanation of each of these topics the words “statement”, “expression” and “block” will be used without defining them again. If you don't pin down the difference between them now, you'll have to either go back for the definition or infer it from context — and not always correctly. This is a short lesson precisely because it introduces vocabulary, not new mechanics: you already wrote both statements and expressions in the previous lesson, you just didn't call them that yet.
03Statement and expression
The code inside main() consists of statements — complete actions. Almost every statement ends with a semicolon ;.
int main()
{
int x = 10;
x = x + 5;
return 0;
}
Inside statements you often find expressions — constructs that are evaluated and yield a value (and sometimes also produce a side effect along the way — for example, change a variable). In the line x = x + 5; both concepts are present at once: x + 5 is an expression, it evaluates to the value 15. The entire line x = x + 5; as a whole is an assignment statement: it takes the value of the expression x + 5 and stores it in the variable x.
Statement and expression are not mutually exclusive categories, but two different levels of the same code: an expression evaluates to a value, a statement is what the execution sequence of a program is built from. The piece x + 5 by itself is an expression, not a statement: it has no ;, and it is not a standalone step of the program. But if you append a ; to it, you get x + 5; — and that is already a separate statement built from an expression (it is called an expression statement); this exact case is examined in the “Common mistakes” section below — the compiler will accept such a line, but the computed value will not be stored anywhere, it will be lost. Other statements are structured differently and are not expression statements: int x = 10; is a declaration statement, return 0; is a return statement, { ... } is a compound statement (a block, see below). You don't need to memorize all the kinds yet — what matters is not to confuse “expression” (evaluates a value) with “statement” (organizes program execution) and to know that the former becomes the latter if you add ;.
At the same time, an expression is not always “just a value with no consequences”: x++ is also an expression, but when evaluated it also changes x; a function call like foo() is also an expression, and it can do anything inside itself, including printing text (as in the next paragraph). The details aren't needed right now, but it's useful not to memorize “an expression does nothing” as an absolute rule.
From the previous lesson: std::cout << "Hello, C++!\n"; is also a statement (an expression statement, built from the expression std::cout << "Hello, C++!\n"), and the "Hello, C++!\n" inside it is a string literal, also a kind of expression (it has a value — the string itself).
04Code blocks
Curly braces { } group several statements into one block (a compound statement) — the body of the main() function as a whole is such a block. Everything inside { } executes in order, top to bottom, as a single unit.
{
int y = 1;
y = y + 1;
std::cout << y;
}
This division — statement / expression / block — will come up in every next lesson: an if has a block that executes if the condition is true; a loop has a block that repeats; a function has a block that runs when it is called. So it's useful to cement it now, on the simplest example, rather than sorting it out in parallel with a new topic later.
05An expression can be evaluated right on the spot
You don't have to first store the result of an expression in a variable and then output it separately — the expression can be evaluated directly inside a std::cout call:
int x = 10; // declaration statement — x exists and equals 10
x = x + 5; // assignment statement — inside it, the expression x + 5
std::cout << x; // outputs the already-computed value of x (15)
std::cout << (x + 100); // the expression x + 100 is evaluated right here — prints 115, x itself does not change
In the last line nothing is stored in a variable — x + 100 is evaluated, the resulting value is immediately passed to std::cout, and x itself remains equal to 15. The parentheses around x + 100 are not required here, but they make the code clearer — it is explicitly visible exactly what constitutes one expression.
06Statement or expression — table
| Code | What it is | Explanation |
|---|---|---|
x + 5 | expression | is evaluated, yields the value 15; without ; it is not a statement, by itself it is not stored and not output |
x + 5; | statement (expression statement) | the same expression x + 5, but with ; — a syntactically complete statement; the value is evaluated and immediately discarded (see “Common mistakes”) |
x++ | expression with a side effect | evaluates a value and changes x — an example that an expression is not always “just a value with no consequences” |
x = x + 5; | statement (assignment) | takes the value of the expression x + 5 and stores it in x |
int x = 10; | statement (declaration) | creates the variable x and immediately initializes it with the value 10 |
std::cout << x; | statement (expression statement) | built from the expression std::cout << x, where x is a nested expression that evaluates to its current value |
{ ... } | block (compound statement) | groups several statements into one unit |
07Worse → better: an intermediate variable used only once
The task is to output x + 100. Three ways to solve it, from unnecessary code to idiomatic.
int x = 10;
x = x + 5;
int resultValue = x + 100;
std::cout << resultValue;
It works correctly, but resultValue is declared, used exactly once and never appears again — an extra statement and an extra name that someone has to invent and read, without adding any understanding.
int x = 10;
x = x + 5;
std::cout << (x + 100);
Exactly the same behavior, without the intermediate step — this is what section 05 above teaches and what the practice below checks (task 2). The rule is not absolute: if the expression were long and unclear without context, a variable with a good name could, on the contrary, make the code clearer — but x + 100 is short and self-evident enough that inline is the better choice.
int x = 10;
x = x + 5;
std::cout << "x = " << x << ", x + 100 = " << (x + 100) << "\n";
Here the << chain from the previous lesson is combined with the inline evaluation from this one — one readable output instead of two disconnected std::cout statements. You don't always need to bring the code to exactly this form — but it's useful to see that both techniques combine.
08Try changing it
Before moving on to the practice below, experiment with the example from section 05 right in the code editor on this page:
- Replace
std::cout << (x + 100);withstd::cout << (x * 2);— the result becomes 30, not 115. - Add one more statement
x = x + 1;between the assignment and the output — the final value ofxchanges by one. - Try removing the
;at the end of any statement — the compiler will refuse to build the program (see common mistakes below).
09Live debugging: common mistakes
The exact error text depends on the compiler and its version — below is a typical g++-style appearance.
; at the end of a statementint x = 10;
x = x + 5 // forgotten ; at the end of the statement
return 0;
The error is tied to line 5, although the real cause is at the end of that same line: the compiler only realizes something is missing when it reaches return on the next line.
x + 5; // evaluated and immediately discarded — the result is not stored anywhere
This is a syntactically correct expression statement (expression statement, see section 03) — the compiler will accept it without a single error or warning in the console, evaluate x + 5 and discard the result. It is more dangerous than a syntax error precisely because the compiler stays silent, and the program's result simply will not be what was expected.
int x = 10;
int x = 20; // not an assignment, but a redeclaration — an error
The compiler usually also points out (“note”) where the first declaration was. To change the value of an existing variable, use assignment without int: x = 20;.
10Check yourself
Three questions on different things: classification (“what is it”), predicting the result, and a typical trap. Try answering yourself first — the answer isn't going anywhere.
1)
y + 12)
y = y + 1;3)
{ int y = 1; y = y + 1; }4)
std::cout << y;Show explanation
1) y + 1 is an expression: it evaluates to a value, but without ; it is not a separate step of the program. 2) y = y + 1; is an assignment statement: it takes the value of the expression y + 1 and stores it in y. 3) { ... } is a block (compound statement): it groups two statements inside { }. 4) std::cout << y; is a statement (expression statement), built from the expression std::cout << y. Common mistakes: considering y + 1 without ; already a statement (option a), or conversely — considering that since an expression lies inside, then y = y + 1;/std::cout << y; remain “just expressions” (option b).
int a = 5;
a = a + 2;
std::cout << (a * 2) << "\n";
std::cout << a;Show explanation
First 14, then 7. After a = a + 2; the variable a equals 7. The expression a * 2 in the first output line is evaluated “on the fly” and is not stored anywhere — a itself does not change because of it, so the second line still outputs 7, not the doubled value.
int b = 3;
b + 10;
std::cout << b;Show explanation
It will output 3. The line b + 10; is a syntactically correct expression statement (see §03 and §09): the value 13 is evaluated and immediately discarded, and b does not change — there is no assignment here. To get 13, you need either b = b + 10; (change b) or std::cout << (b + 10); (output the expression directly).
11Practice
★ Add one more statement that changes x (for example, x = x * 2;), and output the final value of x via std::cout.
Section 05 shows that x can be changed several times in a row — what other operation would give a second assignment statement (addition, multiplication, etc.)?
Solution: x = x * 2; — a second assignment statement after x = x + 5;, then std::cout << x; outputs the final value.
★★ Output the expression x + 100 via std::cout, without storing it beforehand in a separate variable.
Section 05 shows that an expression can be evaluated directly inside std::cout, without a separate variable — try substituting x + 100 in the same place where you would normally put x.
Solution: std::cout << (x + 100); — the expression is evaluated directly inside the cout call, no intermediate variable is needed.
★★★ Write a short program from scratch: create a variable with any name and initial value, change its value with at least two different statements, and then output via std::cout an expression with this variable, evaluated right on the spot — without storing it in a separate variable. Choose the specific name, type, numbers and order of actions yourself; use only what was covered in this and the previous lesson.
Start by declaring a variable with any name and initial value — something like int name = number;.
Then change its value at least twice — any form from this lesson will do: name = name + number;, repeated twice with different operations (addition, multiplication, etc.).
At the end, don't store the final expression in a separate variable — evaluate it directly inside std::cout, as in section 05.
Example solution (one of many possible): int score = 5; score = score + 3; score = score * 2; std::cout << (score - 1); — any other set of a variable, two changes and one inline expression will also work.
12What you can do now
Before this lesson you already wrote both statements and expressions — you just didn't call them that and didn't distinguish them consciously. Now you have the vocabulary and the understanding of what stands behind these words:
- You can tell an expression from a statement in any code fragment and explain what criterion you used to determine it.
- You can explain in your own words the difference between “evaluates a value” (expression) and “performs a program step” (statement) — and that the former becomes the latter when
;is added. - You can find an expression inside a larger construct — for example, see
x + 100insidestd::cout << (x + 100);ory + 1insidey = y + 1;. - You can break down a simple C++ program line by line into statements, expressions and blocks — not as an abstract exercise, but to understand what actually happens during execution.
- You can evaluate an expression directly inside a statement (for example, inside
std::cout), without creating an intermediate variable for it — and you understand when that is appropriate and when it is better to store it in a named variable.
13Summary
- A statement is a syntactic unit from which program execution is built; it almost always ends with
;. - An expression is code that is evaluated and yields a value; it can also have a side effect (for example,
x++changesx). - An expression with
;at the end (x + 5;) itself becomes a statement — an expression statement. This is not an exception to the rule, but one of the kinds of statements, alongside declaration, assignment, return statements, etc. - A block
{ }groups several statements into one compound statement. - An expression can be evaluated directly inside another statement (for example, inside
std::cout << ...), without an intermediate variable. - An expression statement without saving the result (
x + 5;by itself) is syntactically correct but meaningless — the computed value is not kept anywhere.
From now on these two words — “statement” and “expression” — will be used without repeated explanations. The next lesson moves from terminology to the programmer's way of thinking itself: how to break a desire into a plan of action before you even start writing code.
The division into statements, expressions and blocks is part of the C++ language itself, not something specific to console programs. Inside any Unreal function — BeginPlay(), Tick(), a delegate handler — the code is structured exactly the same way: a function body is a block consisting of statements, and statements contain expressions. Unreal adds no additional rules here.