Understanding C ++ Compilation

I recently became aware that I have no idea, in general, how the c / C ++ compiler works. I admit that this began in an attempt to understand the headline, but came to the realization that I lacked how the compilation works.

Take Visual C ++, for example; In the Header Files folder, Resource Files folder, and Source Files folder. Is there any value for separating these folders and what you put in them? For me, these are all source files. Take the snippets of code:

Fragment 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; } 

Compiler error: "a1.cpp (3): fatal error C1004: unexpected end of file was detected", where I would expect this because there is no #include in the a1.cpp file, where the main method exists, where in the following code fragment

Fragment 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 due to the fact that "main.cpp (6): error C2065:" b ": undeclared identifier". If you included a1.cpp, for example,

Fragment 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 about "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, since I suspect that it has anything to do with her xxxx.h file. If I delete the a1.cpp file from the project in fragment 1, it will compile fine. Clearly what I expected, this is not what I get. Theres a lot of books and tutorials on how to code in cpp, but not as much as cpp handles files and source code at runtime. What's going on here?

+4
source share
7 answers

Your questions are not about the compiler, but about how your IDE handles the entire build system. Build systems for most C / C ++ projects compile each .c or .cpp file separately, and then link the resulting object files together with the final executable. In your case, your IDE compiles any file that you have in the project with a .cpp file name extension and then linking the resulting objects. The behavior you see can be explained as follows:

  • a1.cpp missing ; , therefore, when the IDE tries to compile this file, you get an "unexpected end of file" error message.

  • b not declared anywhere in the compilation block main.cpp , so you get an undefined error message.

  • b exists both in the compilation units main.cpp and a1.cpp (obviously in a1.cpp , and through #include for main.cpp ). Your IDE compiles both of these files - now a1.o and main.o each contain an object named b . When binding, you get a duplicate character error.

The important point that should be removed here, which explains all the behavior that you see, is that your IDE compiles every .cpp file, not just main.cpp and the files that it includes, and then links the resulting objects.

I recommend setting up a test command-line project with the make file you created, which will teach you all the internal development of assembly systems, and then you can apply this knowledge to the internal work of your development environment.

+6
source
  • header files do not compile
  • the #include directive literally inserts the contents of the embedded file instead of the #include line
  • All source files (redargless of main) are compiled into .o or .obj files.
  • All obj files are linked with external .lib files, if any
  • You get an executable file.

Regarding point 2:

 example //ah int //bh x = //ch 5 //main.cpp #include <iostream> int main() { #include "ah" #include "bh" #include "ch" ; std::cout << x << std::endl; //prints 5 :) } 

This is not a complete answer, but hth, my2c, etc. :)

+3
source

Since there seem to be two ways to understand your question, I will answer the C ++ compilation part.

I suggest you start by reading the definition of β€œcompiler” on Wikipedia. After that, try doing a Google search for compiler tutorials to create an impression of compilers. More specifically for C ++, you can read the #include and preprocessor instructions (try searching these terms on Google).

If you still want to understand compilers, I suggest a book of compilers. You will find a good list of books at StackOverflow.

+2
source

The #include statement inserts this file into the file, creating #include. Thus, your fragment 3 main.cpp becomes next before compilation.

  // main.cpp // All sorts of stuff from iostream //a1.cpp int b = 4; void main() { cout << b; } 

The reason you get the linker error is because you define b twice. It is defined in a.cpp and main.cpp.

You can read about the declaration and definition.

+1
source

You tell the build system which files to compile. In the case of Visual C ++, it will automatically compile any file named "* .cpp" that you add to the project. Although you can go into the project settings and say that it is not.

It will not compile files named * .h (although it may, if you explain it.)

The #include directive is what the compiler processes before it performs any compilation (it is called a preprocessor). Basically, he takes the file that he points to and inserts it into the source file compiled at the point at which the #include directive is pointed out. Then the compiler compiles it all as a whole.

So in your examples:

Fragment 1

Bote a1.cpp and main.cpp are compiled by the build system. SO, when it encounters an om a1.cpp error, it reports it.

Fragment 2

Note that it compiles these files separately, without knowing each other, so when your link b is in main.cpp, it does not know that b is defined in a1.cpp.

Fragment 3

Now you have included a1.cpp in main.cpp, so it compiles main.cpp, sees the definition for b and says: OK I have b in the global scope. Then it compiles a1.cpp and says β€œOK”, I have b in the global scope.

Now the linker takes the steps and = tries to put a1 and main together, he; Now I tell you, hey, I have a 2nd place on a global scale. Not good.

+1
source

The compiler selects the source files from which you are pointing. In the case of Visual C ++, there the IDE tells the compiler what to do, and different folders are there because the IDE organizes the files.

In addition, the error in fragment 2 comes from the linker, not from the compiler. The compiler compiled main.cpp and a1.cpp into the main.obj and a1.obj object files, and then the linker tries to make an executable by combining these object files, but the variable b is in both a1.obj (directly) and main .obj (via include a1.cpp), so you get an "already defined" error.

0
source

The problems you see in cases 1 and 3 depend on VS. VS seems to be trying to compile both main.cpp and a1.cpp.

Case 1: When VS tries to compile a1.cpp that has a syntax error (missing semicolon), compilation fails.

Case 2: you did not declare the variable b in your main.cpp or in any included files. Therefore, compilation is not performed.

Case 3: This is a linker error. Due to include, int b was declared in main.cpp as well as in a1.cpp. Since neither of them is static or external, two global variables with the same identifier were declared in the same scope. It is forbidden.

0
source

Source: https://habr.com/ru/post/1344149/


All Articles