Search code examples
c++compilationiostreampreprocessor

Why preprocessed file of simple C++ source file contains thousands lines of code?


I am learning C++. I learned a little about the C++ compilation process and the first step of the compilation process is preprocessing. I am curious what happens to source file after preprocessing so I wrote a few lines of code in C++. Here are my codes:

#include <iostream>

using std::cout;
using std::endl;

#define PI 3.1416
int main()
{
    cout << "Hello World\n";
    cout << "The value of PI is: " << PI << '\n'; 
}

Not more than ten lines of code.

I use this compiler flag g++ -E main.cpp > main.p so the preprocessed file is main.p. The preprocessed file main.p contains 28634 lines of code.

First 15 lines of main.p looks like:

# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "/usr/include/c++/9/iostream" 1 3
# 36 "/usr/include/c++/9/iostream" 3
       
# 37 "/usr/include/c++/9/iostream" 3

# 1 "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" 1 3
# 252 "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" 3

# 252 "/usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h" 3

And last 10 lines of main.p looks like:

using std::cout;
using std::endl;


int main()
{
    cout << "Hello World\n";
    cout << "The value of PI is: " << 3.1416 << '\n';
}

Why do main.p contains so many lines of code? My hypothesis (Please correct me if I am wrong) is that all the codes used to build iostream library are included in main.p file, if so then isn't binary or executable of main.cpp unnecessarily big?


Solution

  • Your hypothesis is correct: the entire contents of the iostream header are included in the preprocessor output. And this happens transitively: every header included by iostream is also included, and so on. This is essentially what #include means!

    However, this does not mean that your executable will be big:

    • Headers typically contain only declarations, not implementations. Declarations don't contain any executable code. The actual implementation is in a shared library.
    • Many headers in the standard library contain just templates, which don't emit any code until they're instantiated.
    • Inline implementations are allowed in headers, but they are inlined in the call site, so as long as you don't call them they won't be compiled either.