I googled nearly three pages about static in C language, but found that there is very little information available. Some of them are long and incomprehensible, or they skip a few words at the key points. For beginners who want to explore the underlying principles, it is not very useful. Therefore, I have learned from many sources, integrated and classified the information on the Internet, and wrote a program to verify it myself.
C language code is organized in files. In all source files of a source program, an external variable (note that it is not a local variable) or function can only be defined once in a source program. If there is a duplicate definition, the compiler will report an error. With the mutual reference and independent relationship between variables and functions in different source files, the extern and static keywords are generated.
Below, we will analyze in detail the three major usages of the static keyword when writing programs:
1. static global variables
We know that the layout of a process in memory is shown in Figure 1:
The .text segment stores the binary file of the program executed by the process, the .data segment stores all initialized global variables of the process, and the .bss segment stores uninitialized global variables of the process (there are many other messy segments in other segments, which will not be discussed for now). During the entire life cycle of the process, the data in the .data segment and the .bss segment live and die with the entire process, that is, these data will die only after the process ends.
When a global variable of a process is declared as static, its Chinese name is static global variable. Static global variables are stored in the same place as other global variables, in the .data segment (initialized) or .bss segment (uninitialized), but they are only valid in the source file that defines them, and other source files cannot access them. Therefore, when ordinary global variables put on static clothes, they become brides, with a lover in mind, and can only be accessed by variables or functions in the source file (groom) that defines them.
Here are some example programs
file1.h is as follows:
#include <stdio.h>
void printStr();
Copy code
We define a static global variable hello in file1.c for access by the function printStr in file1.c.
#include "file1.h"
static char* hello = "hello cobing!";
void printStr()
{
printf("%s\n", hello);
}
Copy code
file2.c is the file where our main program is located. If hello is referenced in file2.c, a compilation error will occur
#include "file1.h"
int main()
{
printStr();
printf("%s\n", hello);
return 0;
}
Copy code
The error is as follows:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file2.c: In function 'main':
file2.c:6: error: 'hello' undeclared (first use in this function)
file2.c:6: error: (Even if it appears multiple times in a function, each undeclared identifier
is reported only once in the function in which it file2.c:6: error: is located.)
If we change file2.c to the following form:
#include "file1.h"
int main()
{
printStr();
return 0;
}
Copy the code Then the code
will be compiled and linked successfully.
The results after running the program are as follows:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
hello cobing!
In the above example, hello in file1.c is a static global variable, which can be called by printStr in the same file, but cannot be called by file2.c in a different source file.
Second, static local variables
Ordinary local variables are allocated on the stack. When the function containing the local variable is called multiple times, the position of the local variable on the stack may not be the same each time it is called. Local variables can also be allocated dynamically on the heap, but remember to release the heap space after use.
The Chinese name of static local variable is static local variable. It has the following differences compared with ordinary local variables:
1) Location: Static local variables are placed by the compiler in the global storage area .data (note: not in the .bss segment, see 3) for the reason), so although it is local, it exists throughout the life cycle of the program.
2) Access rights: Static local variables can only be accessed by variables or functions within their scope. That is to say, although it will exist throughout the life cycle of the program, it cannot be accessed by other functions and source files because it is static.
3) Value: If a static local variable is not initialized by the user, it will be automatically assigned a value of 0 by the compiler. Each subsequent call to the static local variable will use the value after the last call. This is relatively easy to understand. Each time a function calls a static local variable, it modifies it and then leaves. The next time it is read, the static local variable read from the global storage area will have the value after the last modification.
The following are some sample programs:
The content of file1.h is the same as in the above example, and the content of file1.c is as follows:
#include "file1.h"
void printStr()
{
int normal = 0;
static int stat = 0; //this is a static local var
printf("normal = %d ---- stat = %d\n",normal, stat);
normal++;
stat++;
}
Copy code
For easy comparison, I defined two variables: normal local variable and static local variable stat, both of which are assigned initial value 0;
file2.c calls file1.h:
#include "file1.h"
int main()
{
printStr();
printStr();
printStr();
printStr();
printf("call stat in main: %d\n",stat);
return 0;
}
Copy code
This call will report an error because file2.c references the static local variable stat in file1.c, as follows:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file2.c: In function 'main':
file2.c:9: error: 'stat' undeclared (first use in this function)
file2.c:9: error: (Even if it appears multiple times in a function, each undeclared identifier
is reported only once in the function in which it file2.c:9: error: is located.)
The compiler says that stat is not declared. This is because it cannot see stat in file1.c. Comment out this line:
#include "file1.h"
int main()
{
printStr();
printStr();
printStr();
printStr();
// printf("call stat in main: %d\n",stat);
return 0;
}
Copy code
liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
normal = 0 ---- stat = 0 normal =
0 ---- stat = 1
normal = 0 ---- stat = 2
normal = 0 ---- stat = 3
Run as shown above. It can be seen that each time the function is called, ordinary local variables are reallocated, while static local variables keep the values of the last call unchanged.
It should be noted that due to this feature of static local variables, functions containing static local variables become non-reentrant, that is, each call may produce different results. This may become a hidden danger in multi-threaded programming. More attention should be paid.
3. Static function
I believe everyone still remembers the private function in C++ object-oriented programming. The private function can only be accessed by the member variables or member functions of the class. In C language, there is also a "private function", which is the static function to be discussed next, which completes the function of the private function in object-oriented programming.
When your program has many source files, you will definitely let a certain source file only provide some interfaces required by the outside world. Other functions may be written to implement these interfaces. You may not want these other functions to be seen by the outside world (not this source file). At this time, you can use static to modify these "other functions".
Therefore, the scope of the static function is the source file. Just think of it as a private function in object-oriented programming.
Here are some examples:
file1.h is as follows:
#include <stdio.h>
static int called();
void printStr();
Copy the code
file1.c as follows:
#include "file1.h"
static int called()
{
return 6;
}
void printStr()
{
int returnVal;
returnVal = called();
printf("returnVal=%d\n",returnVal);
}
Copy code
file2.c calls two functions declared in file1.h, where we deliberately call called():
#include "file1.h"
int main()
{
int val;
val = called();
printStr();
return 0;
}
Copy code
Error when compiling:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
file1.h:3: warning: 'called' is used but never defined
/tmp/ccyLuBZU.o: In function `main':
file2.c.text+0x12): undefined reference to `called'
collect2: ld returns 1
because the static function in file1.h is referenced, so file2.c prompts that this function cannot be found: undefined reference to 'called'
Modify file2.c as follows:
#include "file1.h"
int main()
{
printStr();
return 0;
}
Copy code
Compile and run:
[liujx@server235 static]$ gcc -Wall file2.c file1.c -o file2
[liujx@server235 static]$ ./file2
returnVal=6
Static functions can effectively solve the problem of functions with the same name in different source files, because static functions in one source file are invisible to static functions in other source files.
|