C language foundation - (variable storage method, lifetime, memory mechanism)

Comments from friends are welcome✨✨ This chapter series is a deep thinking and summary of C language, and the content of C language will continue to be updated


foreword

Variable scope: Every variable has a scope, that is, the scope in which they are valid.
Generally, for the convenience of description, the statement that creates a storage space is called a definition such as (int a;), and the statement that does not need to create a storage space is called a statement such as (extern a;).
This chapter will bring you the storage characteristics of data in memory.
There are three possible situations for defining variables:
(1) Defined at the beginning of a function;
(2) Defined within a compound statement within a function;
(3) Defined outside a function.


1. Local variables and global variables

1.1. Local variables

Variables defined inside a function are only valid within the scope of this function, that is to say, they can only be referenced within this function, and these variables cannot be used outside this function. Variables defined in a compound statement are only valid within the scope of this compound statement, and they can only be referenced within this compound statement. These variables cannot be used outside the compound statement, these are called local variables

Explanation:
(1) Variables (such as m, n) defined in the main function are only valid in the main function, and are not valid in the entire file or program because they are defined in the main function. The main function also cannot use variables defined in other functions.

(2) Variables with the same name can be used in different functions, and they represent different objects without interfering with each other. For example, if the variables b and c are defined in the F1 function, if the variables b and c are also defined in the F2 function, they occupy different units in the memory and will not be confused.

(3) Formal parameters are also local variables. For example, the formal parameter a in the F1 function is only valid in the F1 function. Other functions can call the F1 function, but cannot directly refer to the formal parameter a of the F1 function (for example, it is not acceptable to output the value of a in other functions).

(4) Inside a function, variables can be defined in compound statements, and these variables are only valid in this compound statement. This kind of compound statement is also called **"sub-program" or "program block"** variable c is only available
in It is valid within the compound statement (sub-program), and the variable becomes invalid when the compound statement is left, and the system will release the memory unit it occupies.

1.2. Global variables

As mentioned earlier, the compilation unit of a program is the source program file, and a source file can contain one or several functions. Variables defined within a function are local variables , while variables defined outside the function are called external variables , and external variables are global variables ( also called global variables ). Global variables can be shared by other functions in this file. Its effective scope is from the position where the variable is defined to the end of this source file.
Note: Variables defined inside a function are local variables, and variables defined outside a function are global variables.
Explanation: The role of setting global variables is to increase the channel of data connection between functions. Since all functions in the same file can refer to the value of the global variable, if the value of the global variable is changed in one function, it can affect the value of the global variable in other functions. It is equivalent to a direct transfer channel between each function. Since a function call can only bring back one function return value, sometimes global variables can be used to increase the communication channels between functions, and more than one value can be obtained through function calls.
However, it is recommended not to use global variables when necessary, for the following reasons:
① Global variables occupy storage units during the entire execution of the program, instead of opening units only when needed.
② It reduces the versatility of the function, because if a global variable is referenced in the function, the execution will be affected by the relevant external variables. If a function is moved to another file, the relevant external variables should also be considered. Variables and their values ​​are moved over together. However, if the external variable has the same name as a variable in another file, problems will arise. This reduces the reliability and versatility of the program. In program design, modules are required to have strong cohesion and coupling when dividing modulesweak. That is, the function of the module should be single (don't put many irrelevant functions into one module), and the interaction with other modules should be as little as possible, and using global variables is not in line with this principle. It is generally required to make the function in the C program a relative closed body, and there is no other channel except that it can communicate with the outside world through the channel of "actual parameter-formal parameter". Such a program has good portability and strong readability.
③Using too many global variables will reduce the clarity of the program, and it is often difficult for people to clearly judge the value of each external variable at each instant. Because the value of external variables may be changed when each function is executed, the program is prone to errors. Therefore, limit the use of global variables.

Note: If in the same source file, the global variable has the same name as the local variable, the global variable is masked by the local variable, that is, the local variable is valid.

Second, the storage method and lifetime of variables

2.1, dynamic storage method and static storage method

Observed from the perspective of variable scope (that is, from space), variables can be divided into global variables and local variables.
It can also be observed from another angle, that is, from the time when the variable value exists (ie, the lifetime ). Some variables exist during the entire process of program running, while some variables temporarily allocate storage units when the function they are in is called, and the storage unit is released immediately after the function call ends, and the variable does not exist up. In other words, there are two different ways to store variables: static storage and dynamic storage . The static storage method refers to the method that the system allocates a fixed storage space during the running of the program, while the dynamic storage method refers to the method of dynamically allocating the storage space according to the needs during the running of the program.
First look at the storage space for users in the memory. This storage space can be divided into 3 parts:
(1) program area;
(2) static storage area;
(3) dynamic storage area;
data are stored in static storage area and dynamic storage area respectively.
The global variables are all stored in the static storage area , and the storage area is allocated to the global variables when the program starts to execute, and released after the program execution is completed. They occupy fixed storage units during program execution, rather than being allocated and freed dynamically. Store the following data in the dynamic storage area:
Function
formal parameters. Allocate storage for formal parameters when calling a function.
② Variables defined in the function that are not declared with the keyword static are automatic variables.
③ Site protection and return address when the function is called.
For the above data, the dynamic storage space is allocated at the beginning of the function call, and the space is released at the end of the function. During program execution, this allocation and release is dynamic. If the same function is called twice in a program, and local variables are defined in this function, the storage space allocated to these local variables during the two calls Addresses may be different.
If a program contains several functions, the lifetime of the local variables in each function is not equal to the execution cycle of the entire program, it is only a part of the execution cycle of the program.
During program execution, each function is called successively, and storage space is allocated and released dynamically at this time.
In C language, each variable and function has two attributes: data type and data storage class . Storage class refers to the way data is stored in memory (such as static storage and dynamic storage).
When defining and declaring variables and functions, generally their data type and storage class should be specified at the same time, or they can be specified by default (that is, if the user does not specify, the system will implicitly specify a certain storage class).
C storage categories include 4 types: automatic (auto), static (statis), register (register), external (extern). According to the storage class of the variable, the scope and lifetime of the variable can be known. The following are introduced respectively.

2.2, the storage class of local variables

(1) Automatic variable (auto variable)
The local variable in the function, if not specifically declared as static (static) storage category, is dynamically allocated storage space, and the data is stored in the dynamic storage area. Formal parameters in functions and local variables defined in functions (including local variables defined in compound statements) all belong to this category. When the function is called, the system will allocate storage space for these variables, and the storage space will be released automatically when the function call ends. Such local variables are therefore called automatic variables. Automatic variables are declared with the keyword auto as storage class.
In fact, the keyword auto can be omitted. If auto is not written, it is implicitly designated as "automatic storage category" , which belongs to the dynamic storage method. Most variables in the program are automatic variables. The variables defined in the function are not declared as auto, in fact, they are implicitly designated as automatic variables. For example, in the function body:
int ,c=3; is equivalent
to
auto int b,c=3;. (2) Static local variables (static local variables) sometimes hope that the value of the local variable in the function will not disappear after the function call ends and continue to retain the original value, that is, the storage unit occupied by it will not be released. When the function is called next time, The variable already has a value (that is, the value at the end of the last function call). At this time, the local variable should be designated as a "static local variable" and declared with the keyword static.


Explanation:
(1) Static local variables belong to the category of static storage and allocate storage units in the static storage area. It is not released during the entire execution of the program. Automatic variables (ie dynamic local variables) belong to the dynamic storage category, and are allocated in the dynamic storage area instead of the static storage area, and are released after the function call ends.
(2) The initial value is assigned to the static local variable at compile time, that is, the initial value is only assigned once, and it already has an initial value when the program is running. In the future, the initial value will not be reassigned every time the function is called, but the value at the end of the last function call will be retained. The assignment of initial values ​​to automatic variables is not performed at compile time, but at function call time. Each time a function is called, the initial value is assigned again, which is equivalent to executing an assignment statement.
(3) If the initial value is not assigned when defining local variables, then for static local variables, the initial value 0 (for numeric variables) or the null character \0' (for character variables) is automatically assigned when compiling. For automatic variables, its value is an indeterminate value. This is because the storage unit has been released after each function call, and another storage unit is allocated again when the function is called next time, and the content in the allocated unit is unknown.
(4) Although the static local variable still exists after the function call ends, other functions cannot refer to it. Because it is a local variable, it can only be referenced by this function, but not by other functions.

(3) Register variables (register variables)
In general, the values ​​of variables (including static storage methods and dynamic storage methods) are stored in memory. When the value of a variable is used in the program, the controller sends an instruction to send the value of the variable in the memory to the arithmetic unit. The calculation is performed by the arithmetic unit, and if the number needs to be stored, the data is sent from the arithmetic unit to the memory for storage.
If some variables are used frequently (for example, a function is executed 10,000 times in a loop, and a local variable is referenced in each loop), it will take a lot of time to access the value of the variable. In order to improve the execution efficiency, it is allowed to store the value of the local variable in the register in the CPU, and take it out from the register to participate in the operation directly when needed, without going to the memory to access it. This improves execution efficiency since register access is much faster than memory access. This kind of variable is called a register variable and is declared with the keyword register. Such as register int f; //Define f as a register variable
As the speed of computers is getting faster and higher, and the performance is getting higher and higher, the optimized compilation system can identify frequently used variables and automatically put these variables in registers , and does not need to be specified by the programmer. Therefore, there is actually less need to declare variables with register now.
Note: The storage locations of the three kinds of local variables are different: automatic variables are stored in the dynamic storage area; static local variables are stored in the static storage area; registers are stored in registers in the CPU.

2.3, the storage class of global variables

Global variables are stored in the static storage area. Therefore, their lifetime is fixed and exists throughout the running of the program. However, for global variables, there is still a problem to be solved, that is, where does its scope start and where does it end. Does the scope include the entire file range or a part of the file range? Is it valid in a file or in all files of the program? This requires specifying different storage classes.
Generally speaking, an external variable is a global variable defined outside a function, and its scope starts from the definition of the variable to the end of the program file. Within this scope, global variables can be referenced by various functions in the program. But sometimes programmers want to extend the scope of external variables. There are several situations.

(1) Extending the scope of external variables within a file
If an external variable is not defined at the beginning of a file, its effective scope is limited to the point where it is defined to the end of the file. Functions before the point of definition cannot refer to this external variable. If due to some considerations, the function before the definition point needs to refer to the external variable, the keyword extern should be used to make **"external variable declaration"** to the variable before the reference , which means to expand the scope of the external variable to this location. With this declaration, the external variable can be legally used from the declaration. For example:

extern int A , B , C ; //Extend the scope of external variables A, B, C to start from here
int A , B , C ; //Define external variables A, B, C

Note: It is recommended to place the definition of an external variable before all functions that refer to it, so as to avoid adding an extra extern statement in the function.

**(2) Extend the scope of external variables to other files**
A C program can consist of one or more source program files. If the program consists of only one source file, the method of using external variables has been introduced earlier. If a program consists of multiple source program files, what can I do if I want to refer to an external variable defined in another file in one file?
If a program contains two files, the same variable must be used in both files. For an external variable A, you cannot define an external variable A in each of the two files, otherwise a "duplicate definition" error will occur when connecting the program. The correct way is: define the external variable A in any file, and use extern to declare the external , that is, extern A; . When compiling and linking, the system will thus know that A has external linkage , and the defined external variable A can be found elsewhere, and the scope of the external variable A defined in another file will be extended to this file, in this file The external variable A can be legally referenced in .
For example:
file file_1.c:
int A; // define external variables
int main()
{ ... return 0; } file file_2.c: extern A; // extend the scope of external variables defined in file_1.c to this document.




Explanation: Use this method to extend the scope of global variables with caution, because when performing operations in one file, the global value may be changed, which will affect the value of global variables in another file, thereby affecting the value of the global variable in this file. function execution result.
extern can be used not only to expand the scope of external variables in this file, but also to extend the scope of external variables from one file to other files in the program, so how does the system handle it differently? In fact, when compiling When extern, first find the definition of the external variable in this file, if found, expand the scope in this file; if not found, find the definition of the external variable from other files when linking. If it is found from other files, the scope will be extended to this file; if it is not found again, it will be handled as an error.

(3) Limit the scope of external variables to this file

Sometimes in programming, it is hoped that some external variables can only be referenced by this file, but not by other files.
At this time, you can add a static statement when defining the external variable.
For example:
file_1.c
static int A; //Global variables are only limited to be referenced by this text
int main()
{ ... return 0; }


file_2.c
extern A; // Error
void FUN()
{ ... }

A global variable A is defined in filel_1.c, but it uses a static declaration to limit the scope of the variable A to the scope of this file. Although extern A; is used in file_2, it still cannot be used in
filel.c global variable A. Such external variables with static declarations that can only be used in this file are called static external variables . In program design, each module is often completed by several people, and each person can independently use the same external variable name in the file they design without interfering with each other. Just add static when defining external variables in each file. This provides convenience for the modularization and versatility of the program. If it is confirmed that other files do not need to refer to the external variables of this file, you can add static to all the external variables in this file to become static external variables, so as not to be misused by other files. This is equivalent to shielding . From the perspective of other files, this static external variable is invisible and cannot be used . As for the local variables defined in the function in each file, they cannot be referenced outside the function, let alone referenced by other files, so they are safe.

Note: Do not mistakenly think that static storage (stored in static storage area) is adopted after adding static declaration to external variables, and dynamic storage (stored in dynamic storage area) is adopted without adding static. Declaring the storage type of a local variable has a different meaning than declaring the storage type of a global variable. For local variables , the function of declaring the storage type is to specify the variable storage area (static storage area or dynamic storage area) and the resulting lifetime issues, while for global variables , since they are all allocated at compile time The memory is stored in the static storage area, and the function of declaring the storage type is the expansion of the variable scope.

Note: When declaring variables with auto, register and static, these keywords are added on the basis of defining variables, and cannot be used alone. The following usage is incorrect:
int a;//Define the integer variable a
static a //Attempt to declare the variable a as a static variable,
it will be considered **"redefinition"** when compiling.

3. Summary of storage categories

It can be seen from the above that to define a data, two attributes need to be specified: data type and storage class , using two keywords respectively. For example:
static int a; //Static local integer variable or static external integer variable
auto char c; //Automatic variable, defined in the function
register int d; //Register variable, defined in the function In
addition, you can use extern Declare a defined external variable, for example: extern b; //Extend the scope
of the defined external variable b to
this
, there are local variables and global variables. The storage classes they employ are as follows:

局部变量
局部变量
局部变量
局部变量
全局变量
全局变量
按作用域角度分
自动变量:即动态局部变量:离开函数-值就消失
静态局部变量:离开函数-值仍保留
寄存器变量:离开函数-值就消失
形式参数可以定义为自动变量或寄存器变量
静态外部变量:只限本文件引用
外部变量:即非静态的外部变量允许其他文件引用

(2) To distinguish from the time (lifetime) of variable existence, there are two types of dynamic storage and static storage. Static storage exists throughout the runtime of the program, while dynamic storage temporarily allocates units when a function is called.

动态存储
动态存储
动态存储
静态存储
静态存储
静态存储
按变量的生存期分
自动变量:本函数内有效
寄存器变量:本函数内有效
形式参数:本函数内有效
静态局部变量:函数内有效
静态外部变量:本文件内有效
外部变量:用extern 声明后-其他文件可以引用

(3) According to the location where the variable value is stored, it can be divided into:

内存中静态存储区
内存中静态存储区
内存中静态存储区
内存中动态存储区
CPU中的寄存器
按变量值存放位置分
静态局部变量
静态外部变量:函数外部静态变量
外部变量:可以为其他文件引用
自动变量和形式参数
寄存器变量

(4)关于作用域和生存期的概念。从前面叙述可以知道,对一个变量的属性可以从两个方面分析,一是变量的作用域,一是变量值存在时间的长短,即生存期。前者是从空间的角度,后者是从时间的角度。二者有联系但不是同一回事。
如果一个变量在某个文件或函数范围内是有效的,就称该范围为该变量的作用域,在此作用域内可以引用该变量,这种性质也可以称为变量的可见性
如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的生存期,或称该变量在此时此刻存在

(5) static 对局部变量和全局变量的作用不同。对局部变量来说,它使变量由动态存储方式改变为静态存储方式。而对全局变量来说,它使变量局部化(局部于本文件),但仍为静态存储方式。从作用域角度看,凡有 static 声明的,其作用域都是局限的,或者局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)。

Guess you like

Origin blog.csdn.net/weixin_44759598/article/details/128591161