LEARNING · STAGE 00 · PROGRAMMING BASICS

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.

Why Code Looks Like a Spell

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:

  1. Write the desire in a language that has strict rules and that a computer can read — C++.
  2. Explicitly say: “the program can output text” (this capability is provided by a separate set of tools — iostream, connected with a separate line).
  3. Indicate the very point where execution will begin — the main() function.
  4. Inside it — exactly one instruction: take the ready-made output tool (std::cout) and send the required text into it.
  5. Tell the operating system that everything went successfully.
  6. 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++:

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

NameWhat it isNeeded now?
std::coutoutput stream — prints to the consoleyes, used in this lesson
std::endlmanipulator — breaks the line (§14)yes, used in this lesson
std::cininput stream — reads what the user enters from the keyboardno — will appear in one of the next lessons when input is needed
std::cerroutput stream for error messages — separate from cout, so as not to confuse ordinary output with diagnosticsno, not in this course at this stage
std::clogoutput stream for diagnostic logs — similar to cerr, with a different technical buffering settingno, 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 :::

PartWhat it means
stdthe 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”
coutthe 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:

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

WayWhat it doesPeculiarity
"\n"the newline character inside a string literalsimply inserts the character, does nothing else
std::endla separate stream manipulator — also breaks the lineadditionally 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.

Worse — works, but unreadableC++
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.

Better — with \n at the end of each lineC++
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.

Best — one statement, a chain of <<C++
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

ValueExampleResult
Textstd::cout << "Hello";Hello
Integerstd::cout << 100;100
Fractional numberstd::cout << 5.5;5.5
Characterstd::cout << 'A';A
Several values in a rowstd::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; replace 100 with 75 — the result will be Health: 75.
  • Append one more << to the same line: std::cout << "Health: " << 75 << " / " << 100; — you will get Health: 75 / 100.
  • Replace \n with std::endl in 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.

Missing ; at the end of the statement
std::cout << "Hello, C++!"   // missing ; at the end of the statement
return 0;
console (illustration)
g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:6:31: error: expected ';' before 'return' 6 | std::cout << "Hello, C++!" | ^ | ; Compilation failed.

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 cout
cout << "Hello";   // missing std:: before cout
console (illustration)
g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:6:5: error: 'cout' was not declared in this scope 6 | cout << "Hello"; | ^~~~ | std::cout Compilation failed.

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 string
std::cout << Hello;   // without quotes — an identifier, not a string
console (illustration)
g++ main.cpp -o main main.cpp: In function 'int main()': main.cpp:6:18: error: 'Hello' was not declared in this scope 6 | std::cout << Hello; | ^~~~~ Compilation failed.

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.

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

Find the error
What is wrong in this line and why will the compiler not accept 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".

Comparison
How does "\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).

Explain in your own words
Why is the line #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.

★ Add a second line: your name, on a separate line right under “Hello, C++!”. Use \n or std::endl.

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

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 \n or std::endl.
  • You can explain why #include <iostream> is needed, what std:: before cout means, and what the operator << does.
  • You can recognize and fix the three most common beginner mistakes in the very first program: a missing ;, a forgotten std::, and text without quotes.
🎮 And How Is This Connected to Unreal Engine?

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 it std::cout does not work.
  • std:: is an access to a name inside the std namespace, where cout is 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.
  • \n and std::endl both 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.