(1) compilation unit (module)
Compile the code on VC or VS and click the compile button to generate the exe file. The Compiler performs two steps:
Step 1: compile each. cpp (. c) and the corresponding. h file into an obj file;
Step 2: link all the object files in the project to generate the final. EXE file.
The error may occur in two places:
One is a compilation error. This is mainly a syntax error;
One, the Link error, mainly the repeated definition of variables.
The compilation unit refers to each obj file generated during the compilation phase.
An obj file is a compilation unit.
A. cpp (. c) and its corresponding. h file form a compilation unit.
A project consists of many compilation units. Each obj file contains the relative address of variable storage.
(2) Declaration and definition
When a function or variable is declared, it does not give it the actual physical memory space. Sometimes, it can ensure that your program is compiled;
When a function or variable is defined, it has actual physical space in the memory.
If the external variables referenced in the compilation unit are not defined in any part of the project, an error will be reported during the connection even if they can be passed during compilation, because the program cannot find this variable in the memory.
A function or variable can be declared multiple times, but can be defined only once.
(3) effect of extern
Role 1:When it is connected with "C", such as extern "C" void fun (int a, int B );, then the compiler translates the corresponding function name according to the C rule when compiling the function name fun instead of the C ++.
Role 2:When it is not associated with "C" to modify a variable or function, for example, extern int g_nNum; in the header file, it is used to declare the keyword of the function or variable range, the declared functions and variables can be used in the current compilation unit or other compilation units.
That is, to reference the global variables or functions defined in unit A, Unit B only needs to include the header file of unit A. During the compilation phase, although the compilation unit B cannot find the function or variable, it does not report an error. It will find the function from the target code generated by the compilation unit A at the link.
(4) global variable (extern)
Two classes need to use common variables. We define these variables as global variables. For example, res. h and res. cpp are used to declare and define global variables respectively, and global variables are used by ProducerThread and ConsumerThread. (The following is the QT project code)Copy codeThe Code is as follows:/*********** res. h declares the global variable ************/
# Pragma once
# Include <QSemaphore>
Const int g_nDataSize = 1000; // total data volume produced by the producer
Const int g_nBufferSize = 500; // the size of the circular buffer.
Extern char g_szBuffer []; // ring Buffer
Extern QSemaphore g_qsemFreeBytes; // controls the idle zone of the ring buffer (the region in which the producer has not filled the data or the region that the consumer has read)
Extern QSemaphore g_qsemUsedBytes; // controls the use zone in the ring buffer (the region where the producer has filled data but the consumer has not read it)
/**************************/
In the above Code, g_nDataSize and g_nBufferSize are global constants, and others are global variables.Copy codeThe Code is as follows:/*********** res. cpp defines the global variable ************/
# Pragma once
# Include "res. h"
// Define global variables
Char g_szBuffer [g_nBufferSize];
QSemaphore g_qsemFreeBytes (g_nBufferSize );
QSemaphore g_qsemUsedBytes;
/**************************/
When using global variables in other compilation units, you only need to include the header file.Copy codeThe Code is as follows ************/
# Include "consumerthread. h"
# Include "res. h"
# Include <QDebug>
ConsumerThread: ConsumerThread (QObject * parent)
: QThread (parent ){
}
ConsumerThread: ConsumerThread (){
}
ConsumerThread ::~ ConsumerThread (){
}
Void ConsumerThread: run (){
For (int I = 0; I <g_nDataSize; I ++ ){
G_qsemUsedBytes.acquire ();
QDebug () <"Consumer" <g_szBuffer [I % g_nBufferSize];
G_szBuffer [I % g_nBufferSize] = '';
G_qsemFreeBytes.release ();
}
QDebug () <"& Consumer Over ";
}
/**************************/
You can also combine the Declaration and definition of global variables to avoid forgetting the definition. The above extern char g_szBuffer [g_nBufferSize] And # include "res. h "to extern char g_szBuffer [];.
However, this is not good because you cannot use # include "res. h" (if you use it twice or more times, a redefinition error occurs;Note:Even in res. in h, # pragma once, or # ifndef will also be repeatedly defined, because each compilation unit is separate and will be defined separately), then res. other functions or variables declared by h cannot be used unless they are also modified with extern, which is too troublesome, so we recommend that you use it. declare in h ,. the practice defined in cpp.
(5) static global variables (static)
NoteStaticModifying variables does not work.ExternTo modify, that isStaticAndExternIt cannot appear at the same time.
StaticThe modified global variables are declared and defined at the same time, that is, when you useStaticGlobal variables are declared and defined.
The scope of static global variables can only be the compilation unit. When other compilation units use it, they simply copy its value to other compilation units, and other compilation units will open another memory to save it, the modification made by other compilation units does not affect the value in definition. That is, when another compilation unit A uses it, its physical address is different from that of another compilation unit B, neither A nor B can pass any modification made to it to the other party.
Reference the header file where the static global variable is located in multiple places without redefinition errors, because it opens up additional space for storage in each compilation unit.
The following is an example of a Windows console application code:Copy codeThe Code is as follows:/************ res. h **********/
Static charg_szbuffer [6] = "12345 ";
Void fun ();
/************************/
Copy codeThe Code is as follows:/************ res. cpp **********/
# Include "res. h"
# Include <iostream>
Using namespace std;
Void fun (){
For (int I = 0; I <6; I ++ ){
G_szBuffer [I] = 'A' + I;
}
Cout <g_szBuffer <endl;
}
/************************/
Copy codeThe Code is as follows:/************* test1.h **********/
Void fun1 ();
/************************/
Copy codeThe Code is as follows:/************* test1.cpp **********/
# Include "test1.h"
# Include "res. h"
# Include <iostream>
Using namespace std;
Void fun1 (){
Fun ();
For (int I = 0; I <6; I ++ ){
G_szBuffer [I] = 'A' + I;
}
Cout <g_szBuffer <endl;
}
/************************/
Copy codeThe Code is as follows:/************* test2.h **********/
Void fun2 ();
/************************/
Copy codeThe Code is as follows:/************* test2.cpp **********/
# Include "test2.h"
# Include "res. h"
# Include <iostream>
Using namespace std;
Void fun2 (){
Cout <g_szBuffer <endl;
}
/************************/
Copy codeThe Code is as follows:/************ main. cpp **********/
# Include "test1.h"
# Include "test2.h"
Int main (){
Fun1 ();
Fun2 ();
System ("PAUSE ");
Return 0;
}
/************************/
The running result is as follows:
According to our intuitive impression, the output results of fun1 () and fun2 () are both abcdef. In fact, the output of fun2 () is indeed the initial value. Then we track and debug it and find that the g_szBuffer addresses in res, test1, and test2 are different: 0x0041a020, 0x0041a084, and 0x0041a040, which explains why they are different.
Note: When defining static global variables, you usually put them in the. cpp file instead of the. h file. This will not cause unnecessary information pollution to other compilation units.
(6) Global constant (const)
When using const independently, its features are the same as static (the addresses in each compilation unit are different, but it does not matter because it is a constant and cannot be modified ).
When using const and extern together, it features the same as extern.
[Code]
Extern const char g_szBuffer []; // write to. h
Const char g_szBuffer [] = "123456"; // write to. cpp
[/Code