2

I am trying to understand the C++ compilation process in more detail, so I tried to see how the result of C++ pre-processor looks like:

#include <iostream>

int main()
{
    // I am a comment!
    std::cout << "Hi!" << std::endl;
    return 0;
}

I then ran:

g++ -E main.cpp > preprocessed

To run just the preprocessor.

The output is a very long file, since the <iostream> header got expanded along with everything it includes. However, the end of the file looks like this:

...
namespace std __attribute__ ((__visibility__ ("default")))
{

# 60 "/usr/include/c++/4.9/iostream" 3
  extern istream cin;
  extern ostream cout;
  extern ostream cerr;
  extern ostream clog;


  extern wistream wcin;
  extern wostream wcout;
  extern wostream wcerr;
  extern wostream wclog;




  static ios_base::Init __ioinit;


}
# 2 "main.cpp" 2

int main()
{

    std::cout << "Hi!" << std::endl;
    return 0;
}

Expectedly, the comment disappeared, but the preprocessor added some information on lines starting with #.

Are lines beginning with # legal C++? I thought that the sole purpose of # is to designate preprocessor directives. I thought that # is some esoteric way to designate a comment, but this code:

#include <iostream>

int main()
{
    # I am something that follows the hash symbol.
    std::cout << "Hi!" << std::endl;
    return 0;
}

Does not compile.


EDIT:

Apparently # symbols are ok outside the function scope:

g++ -E main.cpp > preprocessed.cpp
g++ preprocessed.cpp -o preprocessed

produces the same executable.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Martin Drozdik
  • 12,742
  • 22
  • 81
  • 146
  • 1
    It sets the file and line number offset that the following section of code comes from, for the purpose of getting the error messages right. – Colonel Thirty Two Apr 03 '15 at 13:49
  • 1
    FWIW, you can compile with -E -P to get rid of them. – chris Apr 03 '15 at 13:52
  • 2
    AFAICT, the C++ standard defines logical compilation steps but the format of the intermediate representation between these steps is implementation defined, so it doesn't have to be "legal" C++ per se. – André Caron Apr 03 '15 at 14:02
  • @AndréCaron it's not implementation-defined – M.M Jul 05 '16 at 09:30
  • Possible duplicate of [What is the meaning of lines starting with a hash sign and number like '# 1 "a.c"' in the gcc preprocessor output?](http://stackoverflow.com/questions/5370539/what-is-the-meaning-of-lines-starting-with-a-hash-sign-and-number-like-1-a-c) – jww Feb 28 '17 at 02:40

1 Answers1

3

The preprocessed C++ code contains lines starting with a # to convey original line number and function call information to the compiler, so it can:

  • produce error information at the appropriate line
  • produce debug information that links with the line numbers

These are called line markers.

A # in this context is not legal C++ code because it signifies a preprocessor directive. But as the file has already been preprocessed, we know it can't mean that, so it is reused in the preprocessed output file for the purpose set out above.

You can get rid of these by using the -P option. From the man page:

-P Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on something that is not C (sic) code, and will be sent to a program which might be confused by the linemarkers.

Note that whilst the manual page refers to C code rather than C++ code (because the manual page is the same for g++ and gcc in this respect), the same consideration applies.

abligh
  • 24,573
  • 4
  • 47
  • 84