Hello World
Choosing a Compiler
There are many C++ compilers.
- GNU compiler collection (GCC): The standard C/C++ compiler provided on most Linux systems. Linux-only.
- Clang: Clang provides various extensions that can be used to build custom compiler add-ons. Cross-platform. Standard on Mac.
- Microsoft Visual C++ (MSVC): The standard C/C++ compiler for Windows.
- Intel Compiler: Sometimes used. Optimizations for intel products.
- MinGW: Like gcc, except works on Windows.
Generally, we prioritize compiling for Linux systems. This means we typically focus on gcc and occasionally clang. Clang is a more modern compiler with many advanced features and better warnings and error messages. However, we generally focus on gcc.
Introduction
In this example, we will demonstrate how print text to a terminal. One of the main use of printing is for debugging. Tools such as Google Logger, are used to make print statements to help determine where a program crashes, without having to use an expensive debugger all the time.
Setup
These tutorials are meant to be worked through inside the tutorial Dev Container, which gives you a ready-made C++ environment (compiler, CMake, debugger, MPI, Boost, spack, cpplint, and the clangd language server) with zero local setup beyond Docker and an editor. See the Dev Containers overview for background.
Prerequisites:
- Docker
- VS Code (or Cursor) with the
Dev Containers
extension (
ms-vscode-remote.remote-containers)
Clone the tutorial and open it in the container:
git clone https://github.com/grc-iit/grc-tutorial.git
cd grc-tutorial
code .
Then open the command palette (Ctrl+Shift+P / Cmd+Shift+P) and run
"Dev Containers: Reopen in Container". VS Code builds the image, installs the
C++ extensions inside the container, and reopens the project there. The
container is defined in the tutorial's .devcontainer/
directory.
Once you are inside the container, the tutorial code is at the workspace root and
the GRC_TUTORIAL environment variable is already defined for you (the Dev
Container sets it to the workspace folder), so the cd ${GRC_TUTORIAL}/cpp/...
commands in the following pages just work — no setup needed.
Docker does not save state outside your workspace. Files you create inside the mounted project directory are preserved on your host, but changes elsewhere in the container are lost when it is rebuilt.
Go to the tutorial:
cd ${GRC_TUTORIAL}/cpp/01-cpp-hello-world
C++ Source File
Below is the code in hello_world.cc.
#include <stdio.h>
#include <iostream>
int main() {
printf("Hello world 0\n");
std::cout << "hello world 1" << std::endl;
return 0;
}
We will describe this step-by-step.
C++ Header Files
#include <stdio.h>
#include <iostream>
#include is used to instruct the C++ compiler where to find header files. In our case, the header files being included are
"stdio.h" and "iostream". Header files typically contain the definitions of functions. They have the same syntax as a source
file, but they don't typically have as much code logic.
To find header files, compilers will search a number of places. For example, "/usr/include" will typically contain "stdio.h"
and "/usr/include/c++" may contain iostream. These paths are subject to change depending on the gcc version and OS.
In our case, "stdio.h" is where printf is defined, and "iostream" is where std::cout is defined.
Program start
int main() {
// code here...
}
The main function is required in order to execute a C++ program. When you launch a program, the main function is where the code execution begins.
Console output
printf("Hello world 0\n");
std::cout << "hello world 1" << std::endl;
- Text is always in double quotes
"" - "
\n" in "Hello world 0" means "new line". Analogous to hitting the Enter key on your keyboard in a text editor. std::coutuses left shift operator (<<) to print to consolestd::endlwrites '\n' and also flushes the output bufferprintftakes the text as a function parameter
Both printf and cout are valid ways of printing. Typically cout is preferred in C++ programs, but you'll likely see
both in example programs.
Program return
int main() {
// code here...
return 0;
}
Main returns an integer "int". This indicates the success or failure of a program. Generally, a return value of "0" indicates
the program succeeded. Any other value indicates a failure and the reason for failure.
Building
We will build this code manually using gcc. In general, building things manually is a bad idea. Build tools (CMake nowadays for C/C++) automate much of the process. However, knowing how the compiler works is helpful.
Here we use gcc to compile the program "hello_world.cc":
g++ hello_world.cc -o hello_world
This produces an executable file called hello_world in the current directory.
Running the Executable
To run the program, give the path to the executable. The leading ./ tells the
shell to look for the program in the current directory:
./hello_world
The expected output is:
Hello world 0
hello world 1
The first line is printed by printf and the second by std::cout.
Checking the Return Code
Every program returns an integer exit code when it finishes. Our main ends
with return 0, and by convention 0 means success — any non-zero value signals
some kind of failure. On Linux, the shell stores the exit code of the most recent
command in $?, so you can inspect it with:
echo $?
The output will be:
0
which is exactly the value we returned from main.