Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding C++ Compilation

I have recently become aware that I have no idea, genericly speaking, how a c/c++ compiler works. I will admit this initialy came from trying to understand header guards but came to the realization that I am lacking in how compiling works.

Take Visual C++ for instance; Theres the "Header Files" folder, the "Resources Files" folder, and "Source Files" folder. Is there any significance to the separation of these folders and what you put in them? To me, they are all source files. Take the code snippets:

Snippet 1

//a1.h
int r=4;

and

//a1.cpp
int b  //<--semicolon left out on purpose

and

//main.cpp
#include <iostream>
#include "a1.h"
void main()
{
   cout << r;
}

The compiler errors out saying "a1.cpp(3) : fatal error C1004: unexpected end-of-file found" where I would expect it wouldn't because the a1.cpp file is not #included where the main method exists where in the next code snippet

Snippet 2

//a1.h
int r=4 //<--semicolon left out on purpose

and

//a1.cpp
int b = 4;  

and

//main.cpp
#include <iostream>
void main()
{
   cout << b;
}

Errors out because "main.cpp(6) : error C2065: 'b' : undeclared identifier". If you include the a1.cpp like so

Snippet 3

//a1.h
int r=4 //<--semicolon left out on purpose

and

//a1.cpp
int b = 4;  

and

//main.cpp
#include <iostream>
#include "a1.cpp"
void main()
{
   cout << b;
}

the compiler complains "a1.obj : error LNK2005: "int b" (?b@@3HA) already defined in main.obj". Both snippets 2 and 3 ignore the fact that int r = 4 does not have a semicolon missing as I suspect that it has something to do with its a xxxx.h file. If I remove the a1.cpp file from the project on snippet 1, then it compiles fine. Clearly what I have expected is not what I am getting. Theres plenty of books and tutorials on how to code in cpp, but not much in the way cpp handles files and source code in the complition process. What on earth is going on here?

like image 748
Chad Harrison Avatar asked Dec 12 '22 15:12

Chad Harrison


1 Answers

Your questions aren't really about the compiler, but about how your IDE is handling the entire build system. The build systems for most C/C++ projects compile each .c or .cpp file separately, and then link the resulting object files together into a final executable. In your case, your IDE is compiling any file you have in the project with a filename extension of .cpp and then linking the resulting objects. The behaviour you're seeing can be explained as follows:

  1. a1.cpp is missing a ;, so when the IDE tries to compile that file, you get the error about 'unexpected end of file'.

  2. b isn't declared anywhere in the main.cpp compilation unit, so you get an error about an undefined identifier.

  3. b exists in both the main.cpp and a1.cpp compilation units (obviously in a1.cpp, and via your #include for main.cpp). Your IDE compiles both of those files - now a1.o and main.o each contain an object called b. When linking, you get a duplicate symbol error.

The important point to take away here, which explains all of the behaviour you see, is that your IDE compiles every .cpp file - not just main.cpp and the files it includes - and then links the resulting objects.

I recommend setting up a command-line test project with a makefile you create yourself - that will teach you all about the inner workings of build systems, and you can then apply that knowledge to the inner workings of your IDE.

like image 116
Carl Norum Avatar answered Dec 30 '22 10:12

Carl Norum