LEARNING · STAGE 00 · PROGRAMMING BASICS

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

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

A block of several statementsC++
{
    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:

Progressive examplesC++
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

CodeWhat it isExplanation
x + 5expressionis 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 effectevaluates 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.

Worse — the variable is needed only onceC++
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.

Better — the expression is evaluated right inside coutC++
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.

Best — both values in a single outputC++
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); with std::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 of x changes 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.

Forgotten ; at the end of a statement
int x = 10;
x = x + 5   // forgotten ; at the end of the statement
return 0;
console (illustration)
g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:5:10: error: expected ';' before 'return' 5 | x = x + 5 | ^ | ; Compilation failed.

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.

An expression written as a standalone statement and the result is lost
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.

Redeclaring a variable in the same block
int x = 10;
int x = 20;   // not an assignment, but a redeclaration — an error
console (illustration)
g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:5:9: error: redefinition of 'int x' 5 | int x = 20; | ^ main.cpp:4:9: note: 'int x' previously declared here 4 | int x = 10; | ^ Compilation failed.

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.

Classification
Below are four code fragments. Only ONE of the answer options classifies ALL four correctly (expression / statement / block). Which one?
1) y + 1
2) 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).

Predict the result
What will this program output?
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.

Find the mistake
The programmer expected to see 13. What will the program actually output?
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.

★★ Output the expression x + 100 via std::cout, without storing it beforehand in a separate variable.

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

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 + 100 inside std::cout << (x + 100); or y + 1 inside y = 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++ changes x).
  • 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.

🎮 How is this related to Unreal Engine?

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.