C++ understands Compiler and Linker through #include

How Compiler work

original Math.cpp:

int Multiply(int a, int b) {
    
    
	int result = a * b;
	return result;
}

Now the demo needs to be split into two files:

EndBrance.h

}

Math.cpp

int Multiply(int a, int b) {
    
    
	int result = a * b;
	return result;
#include "EndBrance.h"

Compile Math.cppwithout error.

The role of the compiler: open EndBrance.hthe file, copy and paste all the contents inside to #include "EndBrance.h"the location.

Please add a picture description

See why by preprocessing the output file

Modify the project property configuration (after configuring the test, remember to cancel the setting):

Please add a picture description

Recompile Math.cpp, a file will be generated in the Debug directory Math.i, open to view the content:

Please add a picture description

It can be seen that the content generated by the compiler Math.cppis contained in the source code, and the compiler embeds #include "EndBrance.h"the in its file into the location.)#include "EndBrance.h"

Similarly, modify the code and check again

such as using#define

#define INTERGER int

INTERGER Multiply(int a, int b) {
    
    
	INTERGER result = a * b;
	return result;
}

After recompiling:

Please add a picture description

For example, use #if, compile and viewMath.i

#if 0
int Multiply(int a, int b) {
    
    
	int result = a * b;
	return result;
}
#endif

Please add a picture description

For example, use it #include <iostream>, check it after compiling, there are more than 50,000 lines in it, and the last is the code I wrote myself. This is because iostreamother file codes are included in .

Please add a picture description


How Linker work

LNK1561

Math.cpp

#include <iostream>

void Log(const char* message) {
    
    
	std::cout << message << std::endl;
}

int Multiply(int a, int b) {
    
    
	Log("Multiply");
	return  a * b;
}

Compile directly, and an error will appear: LNK1561, entry point must be defined. LNKxxx indicates that an error is reported in linking, and Cxxx indicates an error is reported in compilation.

Through project properties, you can customize an entry. The entry point is not necessarily the main function, usually the main function.

Please add a picture description

Add the main function, and recompile will be fine.

int main() {
    
    
	std::cout << Multiply(3, 5) << std::endl;
	std::cin.get();
}

LNK2019

If you change Log.cppthe name of the Log function in the file to Logger, and then just compile (Crtl+F7) Math.cpp, no error will be reported, and the link has not been used in this process.

Please add a picture description

Then, compile the entire project (Ctrl+F5), and an LN2019 error will appear

1>------ 已启动生成: 项目: demo_include, 配置: Debug Win32 ------
1>Math.obj : error LNK2019: 无法解析的外部符号 "void __cdecl Log(char const *)" (?Log@@YAXPBD@Z),该符号在函数 "int __cdecl Multiply(int,int)" (?Multiply@@YAHHH@Z) 中被引用
1>E:\keeplearning\CppCode\VS2017\demo_include\Debug\demo_include.exe : fatal error LNK1120: 1 个无法解析的外部命令
1>已完成生成项目“demo_include.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

Try the following:

  • After commenting out Log("Multiply");, compile the entire project and compile successfully

    #include <iostream>
    
    void Log(const char *);
    
    int Multiply(int a, int b) {
          
          
    	// Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    
  • After commenting out mainthe call in the function, compile the entire project, and the compilation fails

    #include <iostream>
    
    void Log(const char *);
    
    int Multiply(int a, int b) {
          
          
    	Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	// std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    
    1>------ 已启动生成: 项目: demo_include, 配置: Debug Win32 ------
    1>Math.obj : error LNK2019: 无法解析的外部符号 "void __cdecl Log(char const *)" (?Log@@YAXPBD@Z),该符号在函数 "int __cdecl Multiply(int,int)" (?Multiply@@YAHHH@Z) 中被引用
    1>E:\keeplearning\CppCode\VS2017\demo_include\Debug\demo_include.exe : fatal error LNK1120: 1 个无法解析的外部命令
    1>已完成生成项目“demo_include.vcxproj”的操作 - 失败。
    ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
    

    The reason is that even if the Multiply function is not actually called in this file, it may be used in other files to a certain extent, so the linker needs to link.

  • If you tell the linker that the Multiply function is only used in Math.cppand will not be used in other files, can you not link? Of course, it is also possible. At this time, change Multiply to static (meaning it is only used in this file), recompile the entire project, and there will be no link error.

    #include <iostream>
    
    void Log(const char *);
    
    static int Multiply(int a, int b) {
          
          
    	Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	// std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    

    Of course, if on this basis, // std::cout << Multiply(3, 5) << std::endl;the opening comment in the main function is added, and then the project is compiled, there will also be an error.

In addition to changing Log.cppthe name of the Log function in the file to Logger, if other changes are made, there will be a link error and the compilation will fail:

#include <iostream>
int Log(const char* message) {
    
     // 改变返回值类型
	std::cout << message << std::endl;
    return 0;
}
#include <iostream>
void Log(const char* message, int level) {
    
     // 改变入参个数
	std::cout << message << std::endl;
}

LNK2005

Check whether there are functions or variables with the same and repeated names or features. For example, two functions with the same name have the same return value and input parameters. At this time, the linker does not know which one to link.

  • scene 1

    Log.cpp

    #include <iostream>
    
    void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    

    Math.cpp

    #include <iostream>
    
    void Log(const char *);
    
    void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    
    int Multiply(int a, int b) {
          
          
    	Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    

    Programming project, error:

    1>------ 已启动全部重新生成: 项目: demo_include, 配置: Debug Win32 ------
    1>Log.cpp
    1>Math.cpp
    1>正在生成代码...
    1>Math.obj : error LNK2005: "void __cdecl Log(char const *)" (?Log@@YAXPBD@Z) 已经在 Log.obj 中定义
    1>E:\keeplearning\CppCode\VS2017\demo_include\Debug\demo_include.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
    1>已完成生成项目“demo_include.vcxproj”的操作 - 失败。
    ========== 全部重新生成: 成功 0 个,失败 1 个,跳过 0 个 ==========
    
  • scene 2

    Log.h

    #pragma once
    
    void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    

    Log.cpp

    #include <iostream>
    #include "Log.h"
    
    void InitLog() {
          
          
    	Log("Initialized Log");
    }
    

    Math.cpp

    #include <iostream>
    #include "Log.h"
    
    static int Multiply(int a, int b) {
          
          
    	Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    

    Compile the project and report an error

    1>------ 已启动生成: 项目: demo_include, 配置: Debug Win32 ------
    1>Log.cpp
    1>Math.obj : error LNK2005: "void __cdecl Log(char const *)" (?Log@@YAXPBD@Z) 已经在 Log.obj 中定义
    1>E:\keeplearning\CppCode\VS2017\demo_include\Debug\demo_include.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
    1>已完成生成项目“demo_include.vcxproj”的操作 - 失败。
    ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
    

    #includeHow the statement works: When including a header file, we just put the contents of the header file where the statement exists.

    Therefore, writing both in Log.cppand will lead to repeated definitions of the Log function, resulting in the same problem as Scenario 1.Math.cpp#include "Log.h"

The solution to this problem:

  • method 1

    Change Log.hthe method in to static, other files remain unchanged, and the compilation project passes

    #pragma once
    
    static void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    
  • Method 2

    Replace Log.hthe method in inline with other files unchanged

    #pragma once
    
    inline void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    
  • Method 3

    Log.h

    #pragma once
    
    void Log(const char* message);
    

    Log.cpp

    #include <iostream>
    #include "Log.h"
    
    void Log(const char* message) {
          
          
    	std::cout << message << std::endl;
    }
    
    void InitLog() {
          
          
    	Log("Initialized Log");
    }
    

    Math.cpp

    #include <iostream>
    #include "Log.h"
    
    int Multiply(int a, int b) {
          
          
    	Log("Multiply");
    	return  a * b;
    }
    
    int main() {
          
          
    	std::cout << Multiply(3, 5) << std::endl;
    	std::cin.get();
    }
    
    

Guess you like

Origin blog.csdn.net/qq_31362767/article/details/126971415