1 Basic explanation: extern can be placed before a variable or function to indicate that the definition of the variable or function is in another file, prompting the compiler to find its definition in other modules when it encounters this variable or function. In addition, extern can also be used for link specification.
That means extern has two functions. First, when it is used together with "C", such as: extern "C" void fun(int a, int b); it tells the compiler to compile the function fun. When translating the function name, follow the rules of C to translate the corresponding function name instead of C++. The rules of C++ will change the name fun beyond recognition when translating the function name. It may be fun@aBc_int_int#%$ or something else. This depends on the "temper" of the compiler (different compilers adopt different methods). Why do you do this? Because C++ supports function overloading. I will not discuss this issue too much here. If you have If you are interested, you can search online, I believe you can get a satisfactory explanation!
Second, when extern is not used together with "C" to modify a variable or function, such as in a header file: extern int g_Int; its function is to declare a function or function The scope keyword of global variables, the functions and variables declared by it can be used in this module or other modules. Remember that it is a declaration and not a definition! In other words, if module B (compilation unit) refers to the module (compilation unit) When a global variable or function is defined in A, it only needs to include the header file of module A. During the compilation phase, although module B cannot find the function or variable, it will not report an error. It will retrieve the function or variable from module A when connecting. This function is found in the generated object code.
2 Question: extern variable
An array is defined in a source file: char a[6];
It is declared in another file with the following statement: extern char *a;
Excuse me, is this okay?
Answer and analysis:
1), No, the program will tell you illegal access when it is running. The reason is that a pointer to type T is not equivalent to an array of type T. extern char *a declares a pointer variable rather than a character array, so it is different from the actual definition, causing illegal access at runtime. The declaration should be changed to extern char a[ ].
2) The example analysis is as follows. If a[] = "abcd", then the external variable a=0x61626364 (the ASCII code value of abcd), *a is obviously meaningless
Obviously the space pointed by a (0x61626364) is meaningless and prone to occur Illegal memory access.
3) This reminds us that when using extern, we must strictly correspond to the format of the declaration. In actual programming, such errors are common.
4) Extern is often used in variable declarations. You declare a global variable in the *.c file. If this global variable wants to be referenced, put it in *.h and declare it with extern. .
3 Problem: When the extern function prototype is modified
When the function provider unilaterally modifies the function prototype, if the user continues to use the original extern declaration without knowing it, the compiler will not report an error during compilation. However, during operation, system errors often occur due to missing or excessive input parameters. How should this situation be resolved?
Answer and analysis:
Currently, the industry does not have a perfect solution for handling this situation. The usual approach is for the provider to provide a declaration of the external interface in its own xxx_pub.h, and then the caller includes the header file, thus Skip the extern step. to avoid this error.
The sword has two edges, so for the application of extern, different methods should be chosen in different situations.
4 Question: extern “C”
When using C functions in a C++ environment, it often happens that the compiler cannot find the C function definition in the obj module, causing the link to fail. How to solve this situation?
Answer and analysis:
In order to solve the polymorphism problem of functions when compiling, C++ language will combine the function name and parameters to generate an intermediate function name, but the C language will not, so it will not be found during the link. In the case of corresponding functions, at this time, the C function needs to be linked with extern "C", which tells the compiler, please keep my name and do not generate an intermediate function name for linking.
The following is a standard way of writing:
//At the head of the .h file
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
…
…
// Where the .h file ends
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
5 Question: extern function declaration
It is often seen that extern is placed in front of a function and becomes part of the function declaration. So, what role does the C language keyword extern play in the declaration of a function?
Answer and analysis:
If the keyword extern is included in the declaration of a function, it only implies that the function may be defined in other source files and has no other effect. That is, there is no obvious difference between the following two function declarations:
extern int f(); and int f();
Of course, there is still a use for this, which is to declare functions in the program instead of include "*.h". In some complex projects, I am more accustomed to adding extern modification before all function declarations. The reasons and pros and cons of doing this can be seen in the following example: "Global variables modified with extern"
(1) There are the following statements in test1.h:
#ifndef TEST1H
#define TEST1H
extern char g_str[]; //Declare the global variable g_str
void fun1();
#endif
(2) In test1.cpp #include "test1.h"
char g_str[] = "123456"; // Define the global variable g_str
void fun1() { cout << g_str << endl; }
(3) The above is the test1 module. Its compilation and connection can pass. If we also have the test2 module and want to use g_str, we only need to add it to the original file Just quote it in
#include "test1.h"
The above test1 and test2 can be compiled and connected at the same time. If you are interested, you can Use ultraEdit to open test1.obj. You can find the string "123456" in it, but you cannot find it in test2.obj. This is because g_str is a global variable of the entire project and only one copy, test2, exists in the memory. There is no need to have another copy of the .obj compilation unit, otherwise the duplicate definition error will be reported during connection!
(4) Some people like to put the declaration and definition of global variables together to prevent forgetting the definition, such as The above test1.h is changed to
extern char g_str[] = "123456"; // At this time, it is equivalent to no extern
Then remove the definition of g_str in test1.cpp, and then compile and connect the two modules test1 and test2. , a connection error will be reported. This is because you placed the definition of the global variable g_str after the header file. The test1.cpp module contains test1.h, so g_str is defined once, and test2.cpp also contains test1.h, so g_str is defined again, this time the connector finds two g_str when connecting test1 and test2. If you must put the definition of g_str in test1.h, then remove #include "test1.h" from the code of test2 and replace it with:
extern char g_str[];
void fun2() { cout < < g_str << endl; }
At this time, the compiler knows that g_str is an external compilation module and will not define it again in this module. But I want to say that this is very bad. Because you cannot use #include "test1.h" in test2.cpp, you cannot use other functions declared in test1.h, unless they are also modified with extern, in which case the functions you declare will A long list, and the function of the header file is to provide interfaces for external use, so please remember, only make declarations in the header file, the truth is always that simple.
(2) static indicates a static variable. When allocating memory, it is stored in static Area, not stored on the stack.
(1) test1.h:
#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456";
void fun1 ();
#endif
(2) test1.cpp:
#include "test1.h"
void fun1() { cout << g_str << endl; }
(3) 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, and at the same time You can also find them in test2.obj. The reason why they can be connected successfully without reporting a duplicate definition error is because although they have the same content, the physical addresses stored are different, just like two different variable assignments. have the same value, and these two variables act on their respective compilation units. Maybe you are more serious and secretly trace and debug the above code. As a result, you find that the memory address of g_str in the two compilation units (test1, test2) is the same, so you conclude that statically modified variables can also act on other modules, but I I want to tell you that your compiler is deceiving you. Most compilers have optimization functions for the code to achieve the goal of generating a target program that saves memory and has higher execution efficiency. When the compiler connects the various compilation units, Sometimes, it will only copy one copy of the memory with the same content, such as "123456" above. The variables located in the two compilation units have the same content, so only one copy will exist in the memory when connecting. Now, if you change the above code to the following, you can immediately expose the compiler’s lies:
(1) test1.cpp:
#include "test1.h"
void fun1()
{
g_str[ 0] = '' a '';
Cout & lt; & lt; g_str & lt; endl;}}
#include "test1.h"
void fun2 () {core & lt; & lt; & lt ; g_str << endl; }
(3) void main() {
fun1(); // a23456
fun2(); // 123456
}
When you are tracking the code, you will find two The g_str address in the compilation unit is not the same. Because you modified it in one place, the compiler is forcibly restored to the original memory. There are two copies in the memory for the variables in the two modules. It is precisely because static has the above characteristics that when defining static global variables, it is generally placed in the original file instead of the header file, so as not to cause unnecessary information pollution to other modules. Remember this principle too!
Then don’t forget to define it in the original file: const char g_str[] = "123456";