The example details the extern keyword in C and C++

  • 2020-05-10 18:31:55
  • OfStack

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 look for the definition in another module when it encounters the variable or function. extern can also be used for link specification.

That is to say, extern has two functions, the first, when it is used in conjunction with "C"1, such as: extern "C" void fun(int a, int b); It tells the compiler when compiling fun the function name according to the rules of the C to translate the corresponding function name instead of C + +, + + C rules in translating the function name will become fun this name recognition, may be fun @ # % $aBc_int_int may also be other, it depends on the compiler's "temper" (different compiler USES the method of sample 1), why to do so, because C + + support function overloading, Here do not go too much to discuss this problem, if you are interested in can go to the Internet search, I believe you can get a satisfactory explanation!

Second, when extern does not modify a variable or function with "C", as in the 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 this module live other modules, remember it is a declaration is not a definition! Namely B module (compilation unit) if reference module (translation units) A defined in the global variable or function, it can be as long as the header file contains A module, in the compile phase, module B though can not find the function or variable, but it won't be an error, it will be when the connection is found in the target code generated by the module A this function.

2 problem: extern variable

An array is defined in a source file: char a[6];

The declaration was made in another file with the following statement: extern char *a;

Excuse me, is that all right?

Answer and analysis:

1) no, the program will tell you illegal access. The reason is that a pointer to type T is not the same as an array of type T. extern char *a declares a pointer variable instead of an array of characters, so it is different from the actual definition, resulting in illegal access at run time. 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 (ASCII code value of abcd), *a obviously has no meaning

Obviously, the space pointed by a (0x61626364) is meaningless and prone to illegal memory access.

3) this reminds us that when using extern, we should strictly correspond to the format of the declaration. In actual programming, such mistakes are common.

4) extern is often used in variable declarations where you declare a global variable in the *.c file. If the global variable is to be referenced, it is placed in *.h and declared with extern.

3 issues: when the aspect modifies the extern function prototype

When a function provides a single aspect to modify the function prototype, the compiler does not report an error at compile time if the user is unaware of the original extern declaration. However, in the process of running, because of the lack of or more input parameters, it will often become a system error, how to solve this situation?

Answer and analysis:

Currently, there is no perfect solution to this situation in the industry. The usual practice is for the provider to provide a declaration of the external interface in its xxx_pub.h, and then the caller include header file, thereby eliminating the step of extern. To avoid this mistake.

Sword has a double front, for the application of extern, different occasions should choose different practices.

4. Question: extern "C"

When using the C function in C++ environment, it often happens that the compiler cannot find the C function definition in obj module, resulting in the failure of the link. What should I do

What about solving this situation?

Answer and analysis:

C + + language at compile time in order to solve the problems of polymorphic function, function name and parameters will be combined to generate a middle name of the function, the C language is not, so will cause the link can't find the corresponding function, use extern C function is required at this time "C" link specified, this tells the compiler, please keep my name, not to the middle of my generation used to link the function name.

Here's a standard way to write it:


// in .h Head of file 
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
 #endif /* __cplusplus */ 
 ... 
 ... 
 //.h Where the file ends 
 #ifdef __cplusplus
 #if __cplusplus
}
#endif
#endif /* __cplusplus */ 

5 problem: extern function declaration

It is common to see extern in front of a function as part 1 of a function declaration. So, what role does extern, the keyword of C, play in the declaration of a function?

Answer and analysis:

If a function is declared with the keyword extern in it, it is merely a hint that the function may be defined in another source file. That is, there is no obvious difference between the following two function declarations:

extern int f (); And int f ();

Of course, this is still useful, is to replace include "*.h" to declare the function in the program, in some complex projects, I prefer to add extern modification before all the function declaration. The reasons for this and the pros and cons are illustrated by the following example: "global variable modified with extern"

(1) in test1.h there is the following declaration:


#ifndef TEST1H
#define TEST1H
extern char g_str[]; //  Declare global variables g_str
void fun1();
#endif

(2) in test1. cpp


#include "test1.h"
char g_str[] = "123456"; //  Defining global variables g_str
void fun1() { cout << g_str << endl; }

(3) the above is test1 module, which can be compiled and connected. If we also want to use g_str in test2 module, we only need to refer to it in the original file


#include "test1.h"
void fun2() { cout << g_str << endl; }

The above test1 and test2 can be compiled at the same time. If you are interested, you can open test1.obj with ultraEdit. You can find the string "123456" in test2.obj, but you cannot find it in test2.obj. Otherwise this error will be reported on the connection!

(4) some people like to put the declaration and definition of global variables in 1, which can prevent them from forgetting the definition, such as changing test1.h above
extern char g_str[] = "123456"; // this is equivalent to no extern

Then, the definition of g_str in test1.cpp is removed. When compiling the connection between test1 and test2, the connection error will be reported. This is because you put the definition of the global variable g_str after the header file. The module test1.cpp contains test1.h, so g_str is defined once, and test2.cpp also contains test1.h. In this case, the connector finds two g_str when connecting test1 and test2. If you must put the definition of g_str in test1.h, then put the definition of g_str in test1.h

In the code of test2, replace #include "test1.h" with:


extern char g_str[];
void fun2() { cout << g_str << endl; }

When the compiler know g_str is quoted on the outside of a compiler module, will not repeat in this module definition 1 to come out, but I want to say to do so is very bad, because you can't because in test2. Use # include cpp test1. h, then test1. h declared in you cannot use the other functions, unless used extern decorate, also use so you declare function is a big bunch of light, And the purpose of a header file is to provide an interface to the outside world, so keep in mind that the truth is always as simple as making a declaration in a header file.

6. extern and static

(1) extern indicates that the variable has been defined elsewhere, and that the variable is to be used here.

(2) static represents a static variable. When allocating memory, it is stored in a static area, not on the stack.

static scope is the relationship between the internal connection, and extern a bit instead. It is stored separately and the object itself, extern is stored in separate, but can be other objects using extern extern references, and static not ok, use it only allows the object itself. The difference first, static is 1 to "incompatible" with extern guy, that is to say extern and static cannot modify one variable at the same time; Second, static modifies the global variable declaration and definition at the same time, that is, when you declare a global variable using static in the header file, it is also defined; Finally, static modifies the global variable to be scoped only to its own compilation unit, which means that its "global" is only

This compilation unit is valid and cannot be seen by other compilation units, such as:

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

Above two compilation unit can connection is successful, when you open test1. obj, you can find the string in its "123456", at the same time. You can also in test2 obj find them, they can define the connection is successful and to not repeat mistakes because although they have the same content, but the store's physical address is not 1 sample, like two different variable to assign the same value of 1 sample, and the two variables respectively apply to their respective compilation unit. Maybe you is truer, stalked debug the code above, the results you found two compilation unit (test1 test2) g_str memory address is the same, so you jump to conclusions static modified variable can also be applied to other modules, but I want to tell you, that's your compiler is cheating on you, most of the compiler has function of optimizing the code, part of the program to generate more save memory, execution efficiency is higher, when the compiler in the connection of each compilation unit, it will put the same content of memory only 1 copy, For example, "123456" above, the variables in the two compilation units are the same content, so it will only exist in memory at the time of connection, if you change the above code to look like the following, you can immediately expose the compiler's lies:

(1) test1.cpp:


#include "test1.h"
void fun1()
{
g_str[0] = ''a'';
cout << g_str << endl;
}

(2) test2.cpp


#include "test1.h"
void fun2() { cout << g_str << endl; }

(3) void main() {


#ifndef TEST1H
#define TEST1H
extern char g_str[]; //  Declare global variables g_str
void fun1();
#endif
0

At this point, when you trace the code, you will find that the g_str address in the two compilation units is not the same, because you changed it at point 1, so the compiler is forced to restore the original appearance of the memory, and there are two copies in memory for the variables in the two modules to use. Because static has the above features, when defining the static global variable, always put it in the original file instead of the header file, so as not to cause unnecessary information pollution to other modules. Remember this principle as well!

7. extern and const

The global constants modified by const in C++ have the same property as static, that is, they can only be used in this compiled module, but const can be used in conjunction with extern to declare that the constants can be used in other compiled 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 const is used alone it is the same as static, and when it works with extern1 it is the same as extern 1! So I don't have much to say about const. I just want to remind you that const g_str =" 123456" is different from const char g_str[] ="123465". The previous const modifies char * instead of g_str, its g_str is not constant. It is treated as a defined global variable (which can be used by other compilation units), so if you want char*g_str to follow the rules of const's global constant, it is best to define const char* const g_str="123456".


Related articles: