C ++ declaration and definition of global variables

Source: Internet
Author: User

(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 modified with "C", for example, in the header file, extern int g_nnum ;, its function is to declare the keyword of the function or variable's function scope. 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)

[CPP] view plaincopy
/********** Res. h declare 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.

[CPP] view plaincopy
/********* 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.

[Cpp] view plaincopy
************/
# 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 it is used twice or more, 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)

Note: If you use static to modify variables, you cannot use extern to modify them. That is, static and extern cannot appear at the same time.
The static modified global variables are declared and defined at the same time, that is, when you declare the global variables using static in the header file, it is also 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:

[Cpp] view plaincopy
/*********** Res. h **********/
Static charg_szbuffer [6] = "12345 ";
Void fun ();
/************************/

[Cpp] view plaincopy
/*********** 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;
}
/************************/

[Cpp] view plaincopy
/************ Test1.h **********/
Void fun1 ();
/************************/

[Cpp] view plaincopy
/************ 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;
}
/************************/

[Cpp] view plaincopy
/************ Test2.h **********/
Void fun2 ();
/************************/

[Cpp] view plaincopy
/************ Test2.cpp **********/
# Include "test2.h"
# Include "res. H"
# Include <iostream>
Using namespace STD;

Void fun2 (){
Cout <g_szbuffer <Endl;
}
/************************/

[CPP] view plaincopy
/*********** 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.

[Cpp] view plaincopy
Extern const char g_szBuffer []; // write to. h
Const char g_szBuffer [] = "123456"; // write to. cpp

From: http://qiusuoge.com/8839.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.