How C++ Code Is Converted to Machine Code: A Step-by-Step Guide (GCC)

ADITYA SINGHADITYA SINGH
4 min read

C++ is a powerful, high-performance language—but have you ever wondered how your C++ code becomes an executable file your computer can run?

In this blog, we’ll explore how C++ code gets converted into machine code, and how to generate each intermediate file yourself using g++. By the end, you'll have a solid understanding of how your human-readable code ends up as binary instructions executed by a CPU.


🚦 Overview of the Conversion Flow

Here's the general flow from source code to executable:

C++ Code (.cpp)
   ↓
Preprocessing (.i)
   ↓
Compilation to Assembly (.s)
   ↓
Assembly to Object Code (.o)
   ↓
Linking to Executable (no extension or .exe)
   ↓
Execution by CPU (Machine Code)
`

Let’s break each part down.


1️⃣ Writing the Source Code (.cpp)

Create a file named source.cpp:

#include <iostream>
int main() {
    std::cout << "Hello, world!" << std::endl;
    return 0;
}

This is human-readable code written in C++.


2️⃣ Preprocessing (.i file)

The preprocessor handles directives like #include, #define, and macro expansions.

Run this command:

g++ -E source.cpp -o source.i

🔍 What Happens:

  • #include <iostream> is replaced with the full contents of the iostream header file.
  • Macros are expanded.
  • Comments are removed.
  • Output is saved to source.i.

Open source.i to see what the compiler will work on next.


3️⃣ Compilation to Assembly (.s file)

Next, compile the preprocessed code into assembly language.

g++ -S source.cpp -o source.s

🔍 What Happens:

  • Your C++ code is converted to architecture-specific assembly instructions (e.g., x86 or ARM).
  • Output is saved in source.s.

This file is still human-readable but much closer to machine code.


4️⃣ Assembling to Object File (.o file)

Now convert the assembly code into machine code, but not yet executable.

g++ -c source.cpp -o source.o

🔍 What Happens:

  • The assembler converts assembly to machine-level binary.
  • Output: source.o — contains machine code but is not yet executable.

You can’t run this file directly—it still needs linking.


5️⃣ Linking to Executable

This step links your object file with C++ libraries (like the Standard Library).

g++ source.o -o program

🔍 What Happens:

  • The linker resolves all external symbols and references (like std::cout).
  • Combines your object file with library code into a final executable.

Output: program — the complete, runnable file!


6️⃣ Running the Executable

Just run:

./program

You should see:

Hello, world!

🧠 Bonus: Viewing Machine Code

Want to see actual machine instructions?

Use objdump to disassemble the binary:

objdump -d program

This will show assembly-like output of the machine code that the CPU will execute.


🧾 Summary Table

StageCommandOutput FileDescription
Preprocessingg++ -E source.cpp -o source.isource.iExpanded C++ source code
Compilationg++ -S source.cpp -o source.ssource.sAssembly code
Assemblingg++ -c source.cpp -o source.osource.oMachine code (object file)
Linkingg++ source.o -o programprogramFinal executable file
Execution./programRuns the machine code
Disassemblyobjdump -d programShows disassembled machine instructions

🧰 Automating the Full Flow

Here’s a simple shell script to automate all steps:

#!/bin/bash
g++ -E source.cpp -o source.i
g++ -S source.cpp -o source.s
g++ -c source.cpp -o source.o
g++ source.o -o program
echo "Compiled and linked successfully. Run with ./program"

Save as build.sh, make it executable with:

chmod +x build.sh

And run:

./build.sh

👨‍🔧 Final Thoughts

Understanding how C++ code is transformed into machine code is essential for anyone who wants to master systems programming, compiler design, or even just become a more confident developer.

Hopefully, this gave you a clear picture of each step in the compilation toolchain!


💬 If you enjoyed this post or have questions, drop a comment below!

0
Subscribe to my newsletter

Read articles from ADITYA SINGH directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ADITYA SINGH
ADITYA SINGH

I am an Information Science and Engineering student, passionate about Artificial Intelligence, cybersecurity, software development, and problem-solving. I have a strong foundation in data structures and algorithms and was a Top 10 finalist at the SANDBOX 2025 Cybersecurity Hackathon. I’m proficient in Python, C++, SQL, TensorFlow, and PyTorch, and actively contribute to the AI/ML community. On Kaggle, I’m a Notebooks Expert with a global rank of 2,976 out of 57,797 (highest rank: 2,975). Outside academics, I enjoy chess (1500 on Chess.com, 1800 on Lichess), football, badminton, and solving mathematical puzzles.