Loading
All articles
Programming 19 min read

Writing Your First Program in C++: A Visual, Hands-On Guide

Write, compile and run your first C++ program, and understand every line of it: main, #include, std::cout, newlines and std::endl, exit codes, reading compiler errors, reading input, compiler flags, real measurements, and exercises with answers.

nbkhope
On this page

Every programmer's journey starts the same way: making the computer say Hello, World! In C++ that takes just five lines, but those five lines hide a surprising amount: a function the operating system calls, tens of thousands of lines of library code pulled in by a single #include, and a number handed back to the system when the program ends.

In this guide you'll write, compile and run your first C++ program, then take it apart line by line. You'll see what the compiler actually produces, learn to read its error messages (you'll see plenty of them!), print text and numbers, read input from the keyboard, and finish with exercises.

All outputs and measurements below come from real runs with GCC 14.1 (g++) on Windows. Other compilers print slightly different messages, but the programs behave the same.

What you need: a compiler

C++ is a compiled language. You write the program as text (the source code), and a compiler translates it into an executable file of machine instructions your processor runs directly. The three popular compilers are GCC (g++), Clang (clang++) and Microsoft's MSVC.

SystemHow to get a compiler
WindowsInstall MSYS2 and run pacman -S mingw-w64-ucrt-x86_64-gcc for g++, or install Visual Studio with the "Desktop development with C++" workload for MSVC
macOSRun xcode-select --install in the Terminal for clang++ (also available as g++)
LinuxRun sudo apt install g++ (Debian, Ubuntu) or sudo dnf install gcc-c++ (Fedora)

Check that it works:

$ g++ --version
g++.exe (Rev3, Built by MSYS2 project) 14.1.0

From source code to running program

From source code to running program, measured for this article with GCC 14.1 on Windows. 1, Source: hello.cpp, 6 lines and 97 bytes that you write. 2, Preprocessor: follows #include <iostream> and pastes in the library's declarations, about 24,600 lines in g++'s default C++17 mode. 3, Compiler: translates the C++ into machine code, an object file. 4, Linker: joins your code with the standard library's compiled code into hello.exe, 119,167 bytes, or 17,408 bytes with optimizations on and debugging information stripped. 5, Run: the operating system loads the executable and calls main, which prints Hello, World! and returns 0

When you run g++, four things happen in a row:

  1. The preprocessor handles lines starting with #, like #include, by pasting in other files.
  2. The compiler translates the C++ into machine instructions.
  3. The linker joins your code with the compiled standard library into one executable.
  4. You run the executable, and the operating system starts it by calling main.

The smallest C++ program

This is a complete, valid C++ program:

int main() {
}
  • main is the function where every C++ program starts. The operating system calls it when the program launches.
  • int is its return type: main hands an integer back to the system when it finishes.
  • The parentheses () hold the function's parameters; here there are none.
  • The curly braces { } enclose the function's body, the instructions to run. It's empty, so the program starts and immediately ends.

Save it as empty.cpp, then compile and run it. On macOS and Linux:

1$ g++ empty.cpp -o empty
2$ ./empty
3$ echo $?
40

-o empty names the output file. On Windows, g++ adds .exe, and you run it as empty.exe in Command Prompt or .\empty.exe in PowerShell. It prints nothing, as expected. The echo $? shows the number the program handed back: 0. More on that number soon.

Hello, World!

Now let's make it talk. Save this as hello.cpp:

1#include <iostream>
2
3int main() {
4    std::cout << "Hello, World!" << std::endl;
5    return 0;
6}

Compile and run:

$ g++ hello.cpp -o hello
$ ./hello
Hello, World!

Congratulations, you're a C++ programmer! Now let's understand every piece.

The anatomy of Hello, World in C++. #include <iostream> is a preprocessor directive that brings in the input/output library, which defines std::cout and std::endl. int main() { starts the main function, where the program begins; int is the type of value it returns. std::cout << "Hello, World!" << std::endl; sends text to the console: std:: is the namespace prefix, cout is the console output stream, << is the insertion operator that pushes data toward cout, "Hello, World!" is a string literal whose quotes are not printed, std::endl ends the line, and the semicolon ends the statement. return 0; ends main and reports success to the operating system. The closing } ends the function
  • #include <iostream> brings in the input/output stream library, which defines std::cout. The angle brackets < > mean "a standard library header".
  • std::cout (say "see-out", for character output) represents the console. It lives in the std namespace, the standard library's own "folder" of names, hence the std:: prefix.
  • << is the insertion operator: it pushes whatever is on its right into the stream on its left. The arrows point the way the data flows.
  • "Hello, World!" is a string literal: text between double quotes. The quotes themselves aren't printed.
  • std::endl ends the line (more on that below).
  • ; ends each statement, like a period ends a sentence.
  • return 0; ends main and reports success.

What #include really brings in

That one #include line does a lot of work. We asked g++ to show the preprocessor's output (g++ -E) for an empty main with different headers and C++ standards:

What one #include line pulls in: lines of code the compiler actually reads after preprocessing a file with an empty main, measured with GCC 14.1. With no #include: 1 line. With #include <cstdio>, the C-style input/output library: 882 lines. With #include <iostream>: 20,253 lines in C++11, 24,553 in C++17, 29,611 in C++20 and 49,432 in C++23. With #include <print>, the C++23 printing library: 47,158 lines. Each new standard added features to <iostream>, and it more than doubled from C++11 to C++23. With the g++ default, C++17, your 6-line Hello World is about 0.02% of what the compiler reads

Your Hello World is about 0.02% of what the compiler reads, and the newer the C++ standard, the more <iostream> brings along. Don't worry about it for small programs, but it explains why large C++ projects can take minutes to compile, and why you include only what you use.

Lines, "\n" and std::endl

Without a line ending, the output just stops where it is. Take out the << std::endl and the terminal's prompt ends up glued to your text:

$ ./hello
Hello, World!$

There are two ways to end a line:

  • "\n", the newline character, written inside a string. The backslash starts an escape sequence: \n is a newline, \t a tab, \" a double quote and \\ a backslash.
  • std::endl, which writes a newline and flushes the output: it forces everything waiting in the output buffer to be written out right away.

Flushing sounds harmless, but it's slow when you do it a lot. We wrote one million lines to a file both ways:

std::endl vs "\n": time to write one million lines of Hello, World! to a file, measured for this article with GCC 14.1 and -O2 on Windows, median of 5 runs, then the median of 3 program runs. std::endl, which flushes after every line: 3,489 milliseconds. "\n", which lets the stream buffer the output: 68 milliseconds. About 51 times faster. Both files are identical. Use "\n" by default, and std::endl or std::flush only when the output must appear immediately

Same file, about 51 times faster with "\n". Most C++ programmers use "\n" by default, so that's what the rest of this guide does:

1#include <iostream>
2
3int main() {
4    std::cout << "Hello, World!\n";
5    std::cout << "Tabs:\tone\ttwo\n";
6    std::cout << "Quotes: \"C++\" and a backslash: \\\n";
7    return 0;
8}
Hello, World!
Tabs:	one	two
Quotes: "C++" and a backslash: \

Printing more than text

<< can be chained, and it prints numbers and the results of calculations too:

1#include <iostream>
2
3int main() {
4    std::cout << "C++ was first released in " << 1985 << ".\n";
5    std::cout << "2 + 3 = " << 2 + 3 << "\n";
6    std::cout << "7 / 2 = " << 7 / 2 << "\n";
7    std::cout << "7.0 / 2 = " << 7.0 / 2 << "\n";
8    std::cout << "Line one\n"
9              << "Line two\n";
10    return 0;
11}
1C++ was first released in 1985.
22 + 3 = 5
37 / 2 = 3
47.0 / 2 = 3.5
5Line one
6Line two

Notice 7 / 2 printed 3: dividing two whole numbers in C++ throws away the remainder. Make one of them a decimal (7.0) and you get 3.5. A statement can also span several lines; only the ; ends it.

return 0 and exit codes

The int that main returns is the program's exit code: a number the operating system keeps after the program ends. By convention, 0 means success and anything else means some kind of failure.

1#include <iostream>
2
3int main() {
4    std::cout << "Something went wrong!\n";
5    return 3;
6}
1$ ./fail
2Something went wrong!
3$ echo $?
43
5$ ./fail && echo "This only runs if fail succeeded"
6Something went wrong!
7$ ./hello && echo "This only runs if hello succeeded"
8Hello, World!
9This only runs if hello succeeded
What the exit code is for. The program ends with return 0 or return some other number. The shell keeps that number: echo $? shows it in Bash, and $LASTEXITCODE in PowerShell. 0 means success, so a command chained with && runs next; any other number means failure, so the && chain stops. Build tools, scripts and automated tests all check exit codes to decide whether to keep going. If main ends without a return statement, C++ returns 0 automatically

Scripts, build tools and test runners all rely on exit codes. (In PowerShell, use $LASTEXITCODE instead of $?.) As a special rule, if main reaches its closing brace without a return, it returns 0 automatically, which is why the empty program worked. Writing return 0; makes the intent clear.

When things go wrong: compiler errors

You will make typos, and the compiler will catch them before the program ever runs. Learning to read its messages is a superpower. Here's the first mistake everyone makes, a missing semicolon:

1#include <iostream>
2
3int main() {
4    std::cout << "Hello, World!" << std::endl
5    return 0;
6}
1nosemicolon.cpp: In function 'int main()':
2nosemicolon.cpp:4:46: error: expected ';' before 'return'
3    4 |     std::cout << "Hello, World!" << std::endl
4      |                                              ^
5      |                                              ;
6    5 |     return 0;
7      |     ~~~~~~
How to read a compiler error. nosemicolon.cpp:4:46 is the file name, the line number 4 and the column 46. error: expected ';' before 'return' says what went wrong. The next lines quote the code with a caret ^ under the exact spot, and the line below the caret even shows the fix: a semicolon. Tips: fix the first error first, because one mistake can cause a cascade of later errors; the real mistake is often at the end of the line before the one reported; and read the whole message, since GCC often suggests the fix

The format is always file:line:column: error: message, followed by the code with a ^ pointing at the spot. GCC even suggests the fix.

Forget the #include, and the compiler doesn't know what std::cout is:

1int main() {
2    std::cout << "Hello, World!" << std::endl;
3    return 0;
4}
1noinclude.cpp: In function 'int main()':
2noinclude.cpp:2:10: error: 'cout' is not a member of 'std'
3    2 |     std::cout << "Hello, World!" << std::endl;
4      |          ^~~~
5noinclude.cpp:1:1: note: 'std::cout' is defined in header '<iostream>'; this is probably fixable by adding '#include <iostream>'
6  +++ |+#include <iostream>
7    1 | int main() {

(It goes on with the same kind of error for std::endl.) Forget the std:: prefix:

1#include <iostream>
2
3int main() {
4    cout << "Hello, World!" << endl;
5    return 0;
6}
1nostd.cpp: In function 'int main()':
2nostd.cpp:4:5: error: 'cout' was not declared in this scope; did you mean 'std::cout'?
3    4 |     cout << "Hello, World!" << endl;
4      |     ^~~~
5      |     std::cout

And forget a closing quote, and the error points at where the string started:

1#include <iostream>
2
3int main() {
4    std::cout << "Hello, World! << std::endl;
5    return 0;
6}
1typo.cpp:4:18: warning: missing terminating " character
2    4 |     std::cout << "Hello, World! << std::endl;
3      |                  ^
4typo.cpp:4:18: error: missing terminating " character
5    4 |     std::cout << "Hello, World! << std::endl;
6      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
7typo.cpp: In function 'int main()':
8typo.cpp:5:5: error: expected primary-expression before 'return'
9    5 |     return 0;
10      |     ^~~~~~

One typo, two errors: the second is just fallout from the first. Always fix the first error first, then compile again.

What about using namespace std;?

Many tutorials write using namespace std; near the top so they can type cout instead of std::cout. It works, but it pulls hundreds of standard names into your program, where they can clash with your own (try naming a variable count or distance). In small learning programs it's harmless; in real code, and especially in header files, most style guides say to write std::. This guide sticks with std::.

Reading input from the keyboard

std::cin (say "see-in") is the console's input stream, and >>, the extraction operator, pulls a value out of it into a variable:

1#include <iostream>
2
3int main() {
4    int first;
5    int second;
6    std::cout << "First number: ";
7    std::cin >> first;
8    std::cout << "Second number: ";
9    std::cin >> second;
10    std::cout << first << " + " << second << " = " << first + second << "\n";
11    return 0;
12}

A sample run, where the numbers after the colons are typed by the user:

First number: 12
Second number: 30
12 + 30 = 42

int first; declares a variable, a named box that holds one integer. To read a whole line of text, such as a full name, use std::getline with a std::string:

1#include <iostream>
2#include <string>
3
4int main() {
5    std::string name;
6    std::cout << "What's your name? ";
7    std::getline(std::cin, name);
8    std::cout << "Hello, " << name << "! Welcome to C++.\n";
9    return 0;
10}
What's your name? Ada Lovelace
Hello, Ada Lovelace! Welcome to C++.

Useful compiler flags

g++ hello.cpp -o hello is enough to start, but a few flags make the compiler much more helpful:

FlagWhat it does
-o nameNames the executable
-std=c++20Uses the C++20 standard (newer features; -std=c++23 is newer still)
-Wall -WextraTurns on warnings about suspicious code
-O2Optimizes the program for speed
-gAdds debugging information

Warnings point at code that compiles but is probably a mistake:

1#include <iostream>
2
3int main() {
4    int score = 10;
5    int unused = 5;
6    std::cout << "Score: " << score << "\n";
7    return 0;
8}
1$ g++ -std=c++20 -Wall -Wextra warnings.cpp -o warnings
2warnings.cpp: In function 'int main()':
3warnings.cpp:5:9: warning: unused variable 'unused' [-Wunused-variable]
4    5 |     int unused = 5;
5      |         ^~~~~~

Unlike errors, warnings still produce a program, but it's a good habit to fix every one. A good everyday command is g++ -std=c++20 -Wall -Wextra hello.cpp -o hello.

A modern alternative: std::println

C++23 added std::println, which prints with a line ending and fills {} placeholders, a style borrowed from Python and Rust:

1#include <print>
2
3int main() {
4    std::println("Hello, {}!", "World");
5    std::println("{} + {} = {}", 2, 3, 2 + 3);
6}
Hello, World!
2 + 3 = 5

It needs a recent compiler and -std=c++23. With GCC 14 on Windows (MinGW), also add -lstdc++exp at the end of the command. Most existing C++ code and tutorials use std::cout, so it's worth knowing both.

Your turn: practice

Try these before peeking at the answers. Compile each with g++ -std=c++20 -Wall -Wextra.

Exercise 1: Predict the output (warm-up). What exactly does this print?

1#include <iostream>
2
3int main() {
4    std::cout << "One";
5    std::cout << "Two\n";
6    std::cout << "Three\n\nFour\n";
7    std::cout << 10 / 4 << " " << 10.0 / 4 << "\n";
8    return 0;
9}

Exercise 2: Fix the program. This has three mistakes. Find them by compiling it and reading the errors.

1#include <iostream>
2
3int main() {
4    std::cout << "I am learning C++\n"
5    cout << "It is fun!\n";
6    std::cout << "Bye" << std:endl;
7    return 0;
8}

Exercise 3: Draw a box. Write a program that prints exactly this:

+--------+
|  C++!  |
+--------+

Exercise 4: A tiny calculator. Read two whole numbers and print their sum, difference, product and quotient, like this sample run:

1First number: 17
2Second number: 5
317 + 5 = 22
417 - 5 = 12
517 * 5 = 85
617 / 5 = 3

Exercise 5: Temperature converter (challenge). Read a temperature in degrees Celsius as a whole number and print it in Fahrenheit, using the formula F = C × 9 / 5 + 32. Make sure 37 °C gives 98.6, not 98.

Quick quiz

  1. Which function does every C++ program start in?
  2. What does #include <iostream> give you?
  3. What's the difference between "\n" and std::endl?
  4. What does return 0; at the end of main mean?
  5. A compiler reports 10 errors. Which one should you fix first?

Answers

Exercise 1: "One" has no line ending, so "Two" continues on the same line. "\n\n" makes an empty line. 10 / 4 divides whole numbers, giving 2, while 10.0 / 4 gives 2.5:

1#include <iostream>
2
3int main() {
4    std::cout << "One";
5    std::cout << "Two\n";
6    std::cout << "Three\n\nFour\n";
7    std::cout << 10 / 4 << " " << 10.0 / 4 << "\n";
8    return 0;
9}
1OneTwo
2Three
3
4Four
52 2.5

Exercise 2: A missing semicolon at the end of line 4, a missing std:: before cout, and std: with one colon instead of two:

1#include <iostream>
2
3int main() {
4    std::cout << "I am learning C++\n";
5    std::cout << "It is fun!\n";
6    std::cout << "Bye" << std::endl;
7    return 0;
8}
I am learning C++
It is fun!
Bye

Exercise 3: One line of output per statement:

1#include <iostream>
2
3int main() {
4    std::cout << "+--------+\n";
5    std::cout << "|  C++!  |\n";
6    std::cout << "+--------+\n";
7    return 0;
8}
+--------+
|  C++!  |
+--------+

Exercise 4: Remember that / on two ints throws away the remainder:

1#include <iostream>
2
3int main() {
4    int first;
5    int second;
6    std::cout << "First number: ";
7    std::cin >> first;
8    std::cout << "Second number: ";
9    std::cin >> second;
10    std::cout << first << " + " << second << " = " << first + second << "\n";
11    std::cout << first << " - " << second << " = " << first - second << "\n";
12    std::cout << first << " * " << second << " = " << first * second << "\n";
13    std::cout << first << " / " << second << " = " << first / second << "\n";
14    return 0;
15}
1First number: 17
2Second number: 5
317 + 5 = 22
417 - 5 = 12
517 * 5 = 85
617 / 5 = 3

Exercise 5: Writing 9.0 instead of 9 turns the calculation into decimal math, so nothing gets cut off:

1#include <iostream>
2
3int main() {
4    int celsius;
5    std::cout << "Temperature in Celsius: ";
6    std::cin >> celsius;
7    std::cout << celsius << " C = " << celsius * 9.0 / 5 + 32 << " F\n";
8    return 0;
9}
Temperature in Celsius: 37
37 C = 98.6 F
Temperature in Celsius: -40
-40 C = -40 F

With celsius * 9 / 5 + 32, 37 × 9 = 333, and 333 / 5 = 66 in whole-number division, giving 98 instead of 98.6.

Quiz: (1) main. (2) The input/output streams, including std::cout and std::cin. (3) Both end the line, but std::endl also flushes the output buffer, which made writing a million lines about 51 times slower in our test. (4) The program finished successfully: 0 is the "success" exit code. (5) The first one: later errors are often caused by it.

Cheat sheet

I want to…Write
Start a programint main() { … }
Use std::cout and std::cin#include <iostream>
Print textstd::cout << "Hello\n";
Print several thingsstd::cout << "Sum: " << 2 + 3 << "\n";
End a line"\n" (or std::endl to also flush)
Print a tab / quote / backslash\t / \" / \\
Read a numberint age; std::cin >> age;
Read a whole linestd::string line; std::getline(std::cin, line);
Report success / failurereturn 0; / return 1;
Compileg++ -std=c++20 -Wall -Wextra hello.cpp -o hello
Run./hello (macOS, Linux) or hello.exe (Windows)

Wrapping up

Five lines, and now you know what each one does:

  • Every C++ program starts in main, and its int return value is the exit code: 0 means success.
  • #include <iostream> brings in the input/output library; in our measurement, that one line expands to about 24,600 lines (49,432 with C++23).
  • std::cout << prints text, numbers and calculations; std::cin >> reads input.
  • End lines with "\n"; std::endl also flushes, which was about 51 times slower for a million lines.
  • The compiler is your friend: read file:line:column: error, fix the first error first, and turn on -Wall -Wextra.
  • Building means preprocessing, compiling and linking your 97 bytes into a 119 KB executable.

Next, learn how to create a variable in C++, then make decisions with the if statement and repeat things with the for loop. For the bigger picture, read What Is the C++ Programming Language?.

Thanks for reading!

Know someone who would enjoy this? Send it their way.

More articles

Read next

Programming 4 min read

Ruby Blocks and Iterators: Write Your Own

Learn how Ruby methods receive blocks, pass values with yield, handle a missing block, and return an Enumerator. Build and run your own iterator.

nbkhope
Programming 6 min read

C++ std::vector: Size, Capacity, and Safe Growth

Learn how std::vector grows in C++: the difference between size and capacity, when reserve helps, why resize is different, and how growth can invalidate references.

nbkhope
Programming 5 min read

How to Handle Errors in Go: A Hands-On Guide

Learn Go's everyday error pattern with runnable examples: return an error, check it, add context with %w, and recognize a missing file with errors.Is.

nbkhope

Comments

Be kind and specific. Comments with links from new accounts appear after a moderator reviews them.