What a Program Is and How It Runs
The first lesson of the “C++ → Unreal Gateway” course — it begins the path from absolute zero to professional C++ for Unreal Engine 5.8. There is no previously covered topic to lean on here — so the lesson starts from the very beginning: with one simple picture that explains all of programming at once.
01What You Will Learn
- Why a computer is simultaneously the fastest and the dumbest executor — and why the entire profession of programmer follows from that
- The path from source code to a running program: compilation → executable file → main()
- The first complete C++ program — line by line, without omissions
#include,std::cout, the<<operator, strings,\n,std::endl,return 0;- What can be printed to the screen and which errors occur here most often
02The Problem: How to Explain Anything to a Machine
Imagine the smartest person in the world. They can run through a billion possibilities in a second. They have perfect memory. But there is one problem — they do not understand a single human word until you explain everything to them down to the last detail, like a robot.
Tell them, “Bring the book” — and they freeze, because they do not know what “bring” means. Now say it differently: “Turn your head 45 degrees to the left. Find with your eyes a rectangular object on the shelf. Calculate the distance to it. Take three steps forward. Extend your arm. Squeeze your fingers...” — and now they will manage.
That is a computer. The fastest and the dumbest executor at the same time. It does not understand intentions. It understands only precise, step-by-step instructions.
And a programmer is a person who translates a human desire (“let the enemy take damage”, “let a message appear on the screen”) into a language that this machine will understand. That is the whole secret: programming is not magic and not the domain of people with a special mindset. It is the craft of precisely formulating what you want to achieve. Later in this lesson we will break down what stands behind the word “precisely” — through exactly which steps your desire reaches the screen.
Jumping a couple of course stages ahead: if you ever open someone else's code and see something like std::vector<Enemy*> Enemies; — that is not a spell. It is exactly the same phenomenon as a foreman's note “Concrete M300, rebar A400S” at a construction site: incomprehensible to an outsider, extremely specific to someone who knows what each word means. Programmers shorten notation for the same reason a foreman does not spell out the concrete mix composition anew every day — not to create fog, but to avoid drowning in text. A rule for the future: if a construct looks scary — unfold it piece by piece, and the fear will disappear. That is what we will be doing the whole course, construct by construct.
03Algorithm: How a Desire Becomes Text on the Screen
Before writing a single line of C++, let us spell out in words what must happen for “Hello, C++!” to appear on the screen. Still without a single code symbol — just a sequence of steps that a human would understand:
- Write the desire in a language that has strict rules and that a computer can read — C++.
- Explicitly say: “the program can output text” (this capability is provided by a separate set of tools —
iostream, connected with a separate line). - Indicate the very point where execution will begin — the
main()function. - Inside it — exactly one instruction: take the ready-made output tool (
std::cout) and send the required text into it. - Tell the operating system that everything went successfully.
- Translate all this text into machine code — a separate program, the compiler, does that — and only after that run the result.
That is an algorithm — a step-by-step plan of action, not yet tied to the syntax of a specific language. Later in the lesson, each of these six steps will get its own C++ construct: step 2 is #include <iostream>, step 3 is int main(), step 4 is std::cout << "...";, step 5 is return 0;. Section 8 “Line-by-line breakdown of the first program” will show how these six steps map one-to-one onto six lines of real code.
04What the Computer That Executes This Consists Of
So that the future topics of the course (pointers, memory, addresses, and later — UObject and Garbage Collection in Unreal) are not abstract words, it is useful from the very beginning to imagine where program execution physically happens. Computer memory is convenient to imagine as a large city: there are houses (memory cells) in it, and each house has its own number — an address. When a variable like int Health = 100; appears a few lessons from now, it will literally mean “build a small house in this city, hang a Health nameplate on it and put the number 100 inside” — it is just that the address itself is usually hidden behind a convenient name.
- CPU (processor) — executes instructions one after another. It does not “understand” C++ — it understands only machine code (see below).
- Memory (RAM) — that very city of address-houses, temporary storage for data while the program runs.
- Storage (disk) — where files (including the program's executable file) live permanently, even when the computer is off.
- Input/output devices — keyboard, screen, console: through them the program receives data from outside and shows the result.
When you run a program, the operating system loads it from storage into memory, and the CPU starts reading and executing its instructions one after another — exactly what the algorithm from section 3 described, only now we know where it physically happens.
05Source Code and Programming Language
Source code is the text of a program written by a human in a file (for example main.cpp), in a specific programming language — C++ in this case. A programming language is a set of strict rules: which words mean what, where to put ;, how to write a function. Unlike natural language, there is no room for ambiguity here — the compiler either understands a construct strictly by the rules, or issues an error. This is a direct continuation of section 2: since a computer understands only precise instructions, the language in which we write them simply cannot have room for “roughly understandable”.
06Machine Code and the Compiler
The CPU cannot read std::cout << "Hello"; — it understands only machine code: sequences of zeros and ones, each corresponding to one elementary processor operation. C++ source code needs to be translated into such a form — the compiler, a separate program, does that, along with other build tools next to it. The compiler reads the .cpp file, checks that the code is written according to the language rules (otherwise it issues a compilation error and does not run anything), and turns it into a form from which an executable program ultimately results. (Inside this step there are actually several stages — preprocessing, compilation, linking — but for the first acquaintance it is enough to see it as one “compiler” block; details will come later in the course.)
To see this translation not abstractly, let us take a very short function — adding two numbers:
int Add(int A, int B)
{
return A + B;
}
Between this code and the processor there is an intermediate step — assembly, a language that almost directly describes processor actions, but is still readable by a human. On the common x86-64 architecture, the compiler may generate roughly this assembly code for this function:
mov eax, edi
add eax, esi
ret
Step by step: mov eax, edi — “put the first passed number into the processor cell for calculations (the eax register)”; add eax, esi — “add the second number to what lies in this cell”; ret — “return the result to where we were called from”. And even deeper, these three lines turn into pure machine bytes like 89 F8 01 F0 C3 — that is, ultimately into the sequence of zeros and ones that the processor works with. The exact set of bytes is not universal — it depends on the processor, the compiler and optimization settings; what matters is not memorizing bytes, but the whole chain:
Human task → Algorithm → C++ → Compiler → Assembly → Machine code → Processor
In everyday work you will almost never have to descend to this lower level by hand — but knowing that it exists removes the lion's share of mystique around the words “compiler” and “machine code”.
07Executable File and Program Launch
The result of the compiler's work is an executable file (.exe on Windows) — a file the operating system can run directly. When you launch it, the operating system loads it into memory and transfers control to the CPU, which starts executing instructions in order.
08main() — the Entry Point
In an ordinary hosted C++ program, main() is the entry point where the main application scenario begins. The runtime environment calls it after initial preparation. User code can also execute before main, for example in constructors of global objects; our examples currently contain no such code. Libraries do not have their own mandatory main: their functions are called by the application. In this lesson we place all executable learning code inside main.
The whole path, from the file on disk to the text on the screen, looks like this:
main.cpp
│
▼
C++ source code
│
▼
Compiler
│
▼
Machine code
│
▼
Executable file
│
▼
Program launch
│
▼
main()
│
▼
std::cout
│
▼
Console
09The First Program
Here is a minimal complete C++ program that outputs text to the screen — the very six steps of the algorithm from section 3, now in C++:
#include <iostream>
int main()
{
std::cout << "Hello, C++!\n";
return 0;
}
After compilation and launch, this program outputs exactly one line to the console:
Hello, C++!
10Line-by-Line Breakdown of the First Program
#include <iostream> → connects the standard input/output facilities
int main() → the function where execution of an ordinary C++ program begins
{ } → define the function body — everything inside executes in order
std::cout → the object that outputs data to the console
<< → passes data into the output stream
"Hello, C++!" → a string literal — the data to be output
\n → moves the cursor to a new line
; → ends the statement
return 0; → tells the operating system that the program ended successfully
11#include and iostream
C++ by itself does not know how to output text to the screen — this is not built into the language directly. This capability is provided by a separate part of the standard library called iostream (input-output stream). The line #include <iostream> at the beginning of the file tells the compiler: “before compiling this file, substitute the contents of the iostream library here; I will need it”. Without this line the compiler simply will not know what std::cout is, and will issue an error.
<iostream> is not one tool, but a small set of several. In this lesson only the first row of the table is needed; the rest are just a map of what is there, so that they are not a surprise later.
| Name | What it is | Needed now? |
|---|---|---|
std::cout | output stream — prints to the console | yes, used in this lesson |
std::endl | manipulator — breaks the line (§14) | yes, used in this lesson |
std::cin | input stream — reads what the user enters from the keyboard | no — will appear in one of the next lessons when input is needed |
std::cerr | output stream for error messages — separate from cout, so as not to confuse ordinary output with diagnostics | no, not in this course at this stage |
std::clog | output stream for diagnostic logs — similar to cerr, with a different technical buffering setting | no, rarely encountered |
So <iostream> connects this whole group at once — but right now you only need to use std::cout and std::endl; the rest are not magic being hidden from you, just tools from the same set that are not needed yet.
12std::cout and the std Namespace
std::cout consists of two parts separated by :::
| Part | What it means |
|---|---|
std | the namespace of the C++ standard library — a mechanism that groups the library's names and prevents them from conflicting with names you invent yourself |
:: | the scope resolution operator — “look up the name on the right inside what is on the left” |
cout | the standard output stream object itself — what physically outputs data to the console |
Why can't you simply write cout without std::? Because cout is a name defined inside namespace std, not in the global scope. The compiler looks for names where you told it to, and without std:: it will not find it (unless you explicitly write using namespace std;, which this course intentionally does not use — this way it is immediately visible where each name comes from).
13The << Operator
<< here has nothing to do with comparison or mathematics — in the context of std::cout it is the operator that passes the data on the right into the output stream on the left. You can think of it as an arrow: data “flows” in the direction the signs point.
Gradually complicating the example, you can see how it works:
std::cout << "Hello, C++!"; // Hello, C++!
std::cout << 100; // 100
std::cout << 5.5; // 5.5
std::cout << "Health: " << 100; // Health: 100
std::cout << "Health: " << 100 << " / " << 100; // Health: 100 / 100
<< can be repeated any number of times in a row in one statement — each value on the right is simply added to the output immediately after the previous one, with no automatic spaces between them (which is why in the example above the spaces after "Health: " and around "/" are part of the strings themselves, not something << adds). The last line of the example does not accidentally look like a character's health indicator — output of exactly this form will be needed in a live game from the very beginning, as soon as there is even one number that needs to be shown to the player.
14Strings, \n and std::endl
The text in quotes — "Hello, C++!" — is called a string literal: it is data to be output literally as is, unlike, for example, Hello without quotes — in that case the compiler would look for a variable or function named Hello (see typical errors below).
To move to a new line, there are two equally valid ways:
| Way | What it does | Peculiarity |
|---|---|---|
"\n" | the newline character inside a string literal | simply inserts the character, does nothing else |
std::endl | a separate stream manipulator — also breaks the line | additionally forcibly “flushes” the output buffer to the screen — in learning programs the difference is not noticeable, but \n is generally slightly faster |
std::cout << "Hello, C++!\n";
std::cout << "Hello, C++!" << std::endl; // same result
15Worse → Better: Formatting the Output
The same task — output three lines of text — can be solved with different quality. Below are three versions of the same program, from working-but-bad to neat.
std::cout << "Hello, C++!";
std::cout << "Alan";
std::cout << "I am learning C++.";
It compiles without errors and technically “works” — but the result in the console looks like this:
Hello, C++!AlanI am learning C++.
All three lines got glued into one — there is not a single newline in any of the literals, so std::cout simply prints them one after another, exactly as written.
std::cout << "Hello, C++!\n";
std::cout << "Alan\n";
std::cout << "I am learning C++.\n";
The result is already readable — three separate lines:
Hello, C++!
Alan
I am learning C++.
It works correctly, but three separate std::cout << ...; statements in a row — one per line — are visually heavier than they could be, since from §13 we already know that << can be repeated in one statement any number of times.
std::cout << "Hello, C++!\n"
<< "Alan\n"
<< "I am learning C++.\n";
The same result, but now it is visible that this is one logical output, not three that happened to be next to each other. Moving each << to a new code line (this is formatting of the code itself, unrelated to \n) is a common way to read long output chains in real projects, including Unreal code.
16return 0;
main() is declared as a function returning int (int main()) — therefore it must return something to the operating system upon completion. 0 traditionally means the program finished successfully; a non-zero value is usually used to report that the program finished with an error or some other special status — the specific meaning of the number is determined by the program itself (or by operating system conventions).
return 0; in this example is technically not mandatory — modern C++ allows omitting it specifically in main(), and the compiler will silently insert 0 itself. But here you are building an educational foundation, not writing final production code, so return 0; is better written explicitly from the very beginning: this immediately establishes the understanding that a function can return something at all — it will be useful in the very next lessons, when functions with int, bool and other return types appear.
17What Can Be Output — Table
| Value | Example | Result |
|---|---|---|
| Text | std::cout << "Hello"; | Hello |
| Integer | std::cout << 100; | 100 |
| Fractional number | std::cout << 5.5; | 5.5 |
| Character | std::cout << 'A'; | A |
| Several values in a row | std::cout << "HP: " << 100; | HP: 100 |
18Try Changing It
Before moving on to the practice below, it is worth mentally tracing these changes or checking them in your own compiler — not from scratch, but by modifying the ready lines from the examples above:
- In
std::cout << "Health: " << 100;replace100with75— the result will beHealth: 75. - Append one more
<<to the same line:std::cout << "Health: " << 75 << " / " << 100;— you will getHealth: 75 / 100. - Replace
\nwithstd::endlin any line — the result on the screen will not change.
After a couple of such edits, the pattern usually becomes visible: output is simply an alternation of “text” + “value” + “text” + “value”, and it can be controlled freely.
19Live Debugging: Typical Compilation Errors
The exact error text depends on the compiler (g++, Clang, MSVC) and its version — below is shown a characteristic g++-style appearance, so that the first real compilation error is not a complete surprise to you.
; at the end of the statementstd::cout << "Hello, C++!" // missing ; at the end of the statement
return 0;
The error points to line 6 (return 0;), not to the line where the character is actually missing — the compiler only understands this upon reaching the next line. If an error looks strange, it is useful to look at the line above the indicated one.
std:: not specified before coutcout << "Hello"; // missing std:: before cout
Without using namespace std; (which this course intentionally does not use), the compiler does not find cout in the global scope — it is defined inside namespace std. Some compilers even suggest the fix right in the error text, as here.
Hello without quotes is not a stringstd::cout << Hello; // without quotes — an identifier, not a string
The compiler looks for a variable or function named Hello and does not find it — quotes turn text from “a name to look up” into “data to output as is”.
20Check Yourself
Below are questions of different types: not only “what is this”, but also “what will happen”, “what is the difference”, “explain in your own words”. For each question, first try to cover the answer with your hand and think for yourself — the answer opens separately, it is not going anywhere.
std::cout << "Score: " << 10 << "\n"; std::cout << "Score: " << 20;Show explanation
Two lines: Score: 10, and on the next line Score: 20. The first statement ends with the \n character inside the string — this moves the cursor to a new line, and the second statement starts printing right from it.
std::cout << Score; (and nowhere in the program is there a variable Score)Show explanation
Without quotes, Score is not text, but a name that the compiler looks up as a variable or function (see §19, the third error). Since no such variable exists, the compiler will stop with the error “Score was not declared in this scope”. If you need to output the word “Score” as text — quotes are required: "Score".
"\n" differ from std::endl — and is there a situation where it matters at all?Show explanation
Both break the line on the screen — from the point of view of what you will see in this lesson's console, there is no difference. The difference is that std::endl additionally forcibly “flushes” the internal output buffer, while \n does not. In learning programs this is not noticeable; in programs that output a lot of text very quickly, extra forced buffer flushes via std::endl can noticeably slow down output — therefore in real code \n is more often used by default, and std::endl only when a buffer flush is truly needed right now (for example, before an abnormal program termination).
#include <iostream> needed at the beginning of the file, if all the output is done by std::cout, and not by #include itself?Show explanation
C++ as a language contains no built-in way to output text to the screen at all — this capability is provided by a separate library, iostream, not by the language itself (§11). #include <iostream> tells the compiler “substitute the description of this library here before reading the rest of the code” — without this line the compiler simply will not know what the name std::cout means, and will stop with an error even before reaching the question of “does the output itself work”.
21Practice
★ Create a program that outputs: “Hello, C++!”. Use std::cout.
Think about which tool from this lesson can output text to the screen — it was already named in §12.
You need a call of the form std::cout << "..."; — text inside quotes, the statement ends with a semicolon.
Do not forget the newline character \n inside the string itself — otherwise if you add something after it, it will stick right up against it (see §15).
Solution: std::cout << "Hello, C++!\n"; — do not forget #include <iostream> and return 0; around it.
★ Add a second line: your name, on a separate line right under “Hello, C++!”. Use \n or std::endl.
Add the name after the line break: with a separate std::cout statement or by continuing the string literal in the first statement.
The two ways to break a line are equally valid (§14): either \n inside the string, or a separate std::endl after it — both variants will pass the check.
Solution: std::cout << "Alan\n"; (or your own name instead of “Alan”), as the second line right after the first std::cout.
★★ Change the program so that it outputs three lines: “Hello, C++!”, your name and “I am learning C++.” — each line on a new line. This time build all three lines yourself, without ready-made templates.
This is the same action as in task 2, just repeated once more — how many lines total need to be output, and therefore how many output calls should there be in total?
For three separate lines on the screen you need at least two line breaks — one between each pair of adjacent output lines.
Solution: three std::cout calls in a row, each with its own \n at the end: "Hello, C++!\n", then your name with \n, then "I am learning C++.\n".
22What You Can Do Now
Before this lesson, “program” was just a word. Now you have a working model of what happens between the desire (“let text appear on the screen”) and the result on the screen — and you can yourself, without a hint before your eyes, write and explain a program that outputs text over several lines:
- You can explain in your own words why a computer needs extremely precise instructions and not general wishes — and why the very profession of programmer follows from that.
- You can name the whole path from a file with code to text on the screen: source code → compiler → machine code → executable file → launch → main().
- You can independently write a program that outputs one or several lines of text through
std::cout, with a line break through\norstd::endl. - You can explain why
#include <iostream>is needed, whatstd::beforecoutmeans, and what the operator<<does. - You can recognize and fix the three most common beginner mistakes in the very first program: a missing
;, a forgottenstd::, and text without quotes.
In an ordinary C++ program you create main() yourself, and execution begins from it. In Unreal Engine everything is different: the engine provides its own application launch system and game framework, so in game code you usually do not write main() yourself — Unreal takes over this entry point.
But everything else you study in this course — functions, variables, types, classes, pointers, references, structs, memory — will become a direct foundation for working with Unreal C++. That is why later the question “where is Unreal's main()?” will not arise — you will already know that this is an architectural feature of the engine, not something you are doing wrong.
23In Brief
- A program is a sequence of precise instructions; the path from text to result: source code → compiler → machine code → executable file → launch → main().
#include <iostream>connects the input/output facilities — without itstd::coutdoes not work.std::is an access to a name inside thestdnamespace, wherecoutis defined.<<passes data into the output stream; it can be repeated any number of times in a row.- A string in quotes is data for output; without quotes it is a name that the compiler looks up as a variable/function.
\nandstd::endlboth break the line.return 0;reports successful program completion — in this course we always write it explicitly.
The next lesson breaks down what was taken on faith here: why lines like std::cout << "Hello, C++!\n"; are called a “statement” at all, how a statement differs from an expression inside it — and how literally any program you will write later in this course is built from these two concepts.