Before we discuss global variables, we need to understand a few basic concepts:
1. Compilation unit (module):
In the IDE development tools of the big line of the today, some of the concepts of compilation is no longer clear, many programmers are most afraid of is to deal with connection errors (link error), because it is not like a compilation error can give you the exact location of the program error, you are often upset about this error, But if you often use tools such as Gcc,makefile in Linux or embedded under the development work, then you may very well understand the difference between the compilation and the connection! When the VC such development tools to write code, click the Compile button ready to generate EXE file, VC actually did two steps, the first step, will each. cpp (. c) and the corresponding. h files are compiled into obj files; the second step is to link all the obj files in the project to generate the final. exe file, then the error can be generated in two places, one is a compile-time error, this is mainly a syntax error, and the other is a connection error, mainly repeating the definition of variables and so on. What we call a compilation unit is that each obj file generated during the compile phase, an obj file is a compilation unit, that is, a CPP (. c) and its corresponding. h file together make up a compilation unit, and a project consists of a number of compilation units, Each obj file contains the relative address of the variable store, and so on.
2. Differences between declarations and definitions
When a function or variable is declared, it does not give it the actual physical memory space, it can sometimes guarantee that your program compiles, but when the function or variable is defined, it has the actual physical space in memory, if the external variable you reference in the compilation module is not defined anywhere in the project, So even if it can pass at compile time, the connection will also be error, because the program cannot find this variable in the memory! You can also understand that the declaration of the same variable or function can be repeated more than once, but only once!
3. The role of extern
extern has two functions, the first one, when it is combined with "C", such as: extern "C" void fun (int a, int b); Then tell the compiler to compile the function name of fun, according to the C rules to translate the corresponding function name instead of C + +, C + + rules in the translation of this function name will be the name of the fun to become unrecognizable, may be [email protected]_int_int#%$ may also be other, This depends on the "temper" of the compiler (different compiler uses the same method), why do it, because C + + support functions of the overloaded Ah, here do not go too much to discuss the problem, if you are interested can go online search, I believe you can get a satisfactory explanation!
When extern does not decorate a variable or function with "C", as in a header file: extern int g_int; Its function is to declare the function or global variable scope of the keyword, its declared functions and variables can be used in other modules of this module, remember that it is a declaration is not a definition! That is, if the B module (the compilation unit) refers to a global variable or function defined in a module (compilation unit), As long as it contains the header file of the A module, in the compilation phase, module B, although it cannot find the function or variable, but it does not error, it will be in the connection when the module a generated from the target code to find this function.
If you have a good understanding of the above concepts, let's take a look at the following differences in the use of global variables/constants:
1. Global variables modified with extern
The above has been said the role of extern, let us give an example, such as:
The following declarations are made in Test1.h:
#ifndef test1h
#define TEST1H
extern Char g_str[]; Declaring Global Variables G_str
void Fun1 ();
#endif
In the Test1.cpp
#include "Test1.h"
Char g_str[] = "123456"; Defining Global Variables G_str
void Fun1 ()
{
cout << g_str << Endl;
}
The above is the Test1 module, its compilation and connection can pass, if we have test2 module also want to use G_STR, only need to reference in the original file can be
#include "Test1.h"
void Fun2 ()
{
cout << g_str << Endl;
}
The above test1 and test2 can compile the connection through at the same time, if you are interested in the words can be opened with UltraEdit test1.obj, you can be inside the "123456" this string, but you can't find in Test2.obj, this is because g_ STR is a global variable for the entire project, there is only one copy in memory, test2.obj this compilation unit does not need another copy, otherwise it will report a duplicate definition of this error at the time of connection!
Some people like to put the declaration and definition of global variables together, so as to prevent forgetting the definition, such as to change the above Test1.h to
extern char g_str[] = "123456"; This time is equivalent to no extern
Then the definition of test1.cpp in the g_str removed, this time to compile the connection test1 and test2 two modules, the connection error is reported, because you put the definition of the global variable g_str after the header file, Test1.cpp This module contains Test1.h so defines a g_str, and Test2.cpp also contains test1.h so once again the G_STR is defined, when the connector finds two test1 when connecting Test2 and G_str. If you want to put the definition of g_str in the Test1.h, then the Test2 code in the # include "Test1.h" is removed instead:
extern Char g_str[];
void Fun2 ()
{
cout << g_str << Endl;
}
This time the compiler knows that G_STR is a compiled module from the outside, and will not be defined again in this module, but I would like to say that this is very bad because you cannot use # include "Test1.h" in Test2.cpp. Then the other functions declared in the test1.h you can not use, unless you also use the extern decoration, so that your light declaration of the function is a large string, and the role of the head file is to provide external interface to use, so remember, only in the header file declaration, the truth is always so simple.
2. Global variables modified with static
First of all, I'm going to tell you that static and extern are a couple of "fire and Fire" guys, which means that extern and static cannot modify a variable at the same time, and second, the static modification of the global variable declaration and definition at the same time, That is, when you declare a global variable with static in a header file, it is defined at the same time, and finally, the scope of the static modifier global variable is only its own compilation unit, that is, its "global" is only valid for this compilation unit, and other compilation units do not see it, such as:
Test1.h:
#ifndef test1h
#define TEST1H
static char g_str[] = "123456";
void Fun1 ();
#endif
Test1.cpp:
#include "Test1.h"
void Fun1 ()
{
cout << g_str << Endl;
}
Test2.cpp
#include "Test1.h"
void Fun2 ()
{
cout << g_str << Endl;
}
The above two compilation units can be connected successfully, when you open test1.obj, you can find the string "123456" in it, At the same time you can find them in test2.obj, they can be connected successfully without repeating the definition of the error because although they have the same content, but the physical address of the storage is not the same, like two different variables assigned the same value, and the two variables for their respective compilation unit.
Perhaps you are more serious, your own secretly tracking debug the above code, the results you found two compilation units (Test1, test2) of the G_STR memory address is the same, so you can conclude that the static modified variable may also act on other modules, but I want to tell you, that is your compiler is deceiving you, Most compilers have the ability to optimize the code to achieve the resulting target program more memory-saving, more efficient execution, when the compiler is connected to each compilation unit, it will be the same content of the memory copy only one copy, such as the above "123456", in the two compilation unit variables are the same content, Then it will only exist in memory at the time of the connection, if you change the above code to look like this, you can immediately expose the compiler's lies:
Test1.cpp:
#include "Test1.h"
void Fun1 ()
{
G_str[0] = ' a ';
cout << g_str << Endl;
}
Test2.cpp
#include "Test1.h"
void Fun2 ()
{
cout << g_str << Endl;
}
void Main ()
{
Fun1 (); a23456
Fun2 (); 123456
}
This time when you are tracking the code, you will find that the G_STR address in the two compilation unit is not the same, because you modify it in one place, so the compiler is forcibly restored to the original memory, in memory there are two copies of the two modules in the use of variables.
It is because of the above characteristics of static, so the general definition of static global variables, it is placed in the original file instead of the header file, so that the other modules will not cause unnecessary information pollution, the same thing to remember this principle!
3 Const-Modified global constants
Const-Modified global constants are used extensively, such as error message strings in software that are defined with global constants. The const-Modified global constants have the same characteristics as static, that is, they can only be used in this compilation module, but a const may be used with an extern connection to declare that the constant can function in other compilation modules, such as
extern const Char g_str[];
Then, in the original file, don't forget to define:
const char g_str[] = "123456";
So when the const is used alone it is the same as static, and when working with extern, its characteristics are the same as extern! So for const I have nothing to describe too much, I just want to remind you that const char* G_STR = "123456" is different from the const char g_str[] = "123465" and the previous const modifier is char * instead of g_ STR, its g_str is not a constant, it is considered a defined global variable (can be used by other compilation units), so if you like to let Char *g_str abide by the const global constants rules, it is best to define the const char* Const g_str= " 123456 ".
The difference between several methods of defining global variables/constants