The static keyword is a keyword that exists in both C and C ++. It mainly has three usage methods. The first two are only used in C, the third method is used in C ++. (The detailed operations in C and C ++ vary. This document uses C ++ as the standard ).
(1) local static variables
(2) external static variables/functions
(3) static data member/member functions
The following three usage methods and precautions are described respectively.
I. Local static variables
In C/C ++, local variables can be divided into three types: auto, static, and register.
(<C language programming (second edition)> tan haoqiang, pp. 174-175)
Compared with the auto-type (common) local variable, the static local variable has three differences.
1. Different Storage space allocations
The auto type is allocated to the stack and belongs to the dynamic storage class, occupying the dynamic storage space. The function is automatically released after the function call is completed, and the static type is allocated to the static storage area, the program is not released during the entire running period. they have the same scope but different lifetime.
2. Static local variables initialize at the first run of the module and operate only once
3. for local static variables, if no initial value is assigned, the initial value 0 or null characters are automatically assigned during the compilation period, while the initial values of the auto type are uncertain. (except for class objects in C ++, if the class object instance is not initialized, the default constructor is automatically called, regardless of whether the class is static or not)
Features: "Memory" of static local variables and "Global" of lifetime"
The so-called "Memory" refers to the value of the first function call exit when the second function call enters.
Example 1
# Include <iostream>
Using namespace STD;
Void staticlocalvar ()
{
Static int A = 0; // Initialization is performed at runtime. Initialization is not performed for the next call.
Cout <"A =" <A <Endl;
++;
}
Int main ()
{
Staticlocalvar (); // the first call, output a = 0
Staticlocalvar (); // The second call, remembering the value at the first exit, output a = 1
Return 0;
}
Application:
Use "Memory" to record the number of function calls (Example 1)
Improve the problem of "return a pointer/reference to a local object" by using global survival. the problem with the local object is that the function exits and the lifetime ends ,. use static to prolong the lifetime of a variable.
Example 2:
// Ip address to string format
// Used in Ethernet frame and IP header analysis
Const char * iptostr (uint32 ipaddr)
{
Static char strbuff [16]; // static local variable, used to return valid addresses
Const unsigned char * PChIP = (const unsigned char *) & ipaddr;
Sprintf (strbuff, "% u. % u. % u", PChIP [0], PChIP [1], PChIP [2], PChIP [3]);
Return strbuff;
}
Note:
1. "Memory", a very important part of the program running is repeatability, while the "Memory" of static variables damages this repeatability, resulting in different runtime results may be different.
2. global and uniqueness of "Lifetime. the storage space of common local variables is allocated to the stack. Therefore, the allocated space may be different each time a function is called. Static has the global uniqueness feature, all point to the same memory, which leads to a very important problem-re-import is not allowed !!!
In this way, pay special attention to this issue in multi-threaded or recursive programming.
(Examples of non-reentrant properties can be found in <effective C ++ (2nd)> (photoprinting) page 103-105)
The following is an example of Program 2, which is used to analyze the security of multiple threads (to facilitate the description, mark the row number)
① Const char * iptostr (uint32 ipaddr)
② {
③ Static char strbuff [16]; // static local variable, used to return valid addresses
④ Const unsigned char * PChIP = (const unsigned char *) & ipaddr;
⑤ Sprintf (strbuff, "% u. % u. % u", PChIP [0], PChIP [1], PChIP [2], PChIP [3]);
⑥ Return strbuff;
7}
Assume that there are two threads a and B that need to call the iptostr () function during runtime, and convert the 32-bit IP address into a string in the 10th notation. now a gets the execution opportunity and runs iptostr (). The input parameter is 0x0b090a0a. After the execution is complete, the returned pointer storage area is: "10.10.9.11". When the execution ends, if the execution permission is lost, the task is scheduled to run in line B. The parameter passed in line B is 0xa8a8c0 and executed to 7. The content in the static storage area is 192.168.168.168. when it is scheduled again to a for execution, it continues from 6th to 6th. Due to the global uniqueness of strbuff, the content has been washed out by line B. In this case, the returned string is the string 192.168.168.168, not the string 10.10.9.11.
Ii. External static variables/functions
Static in C has a second meaning: it is used to indicate global variables and functions that cannot be accessed by other files ., However, to restrict the scope of global variables/functions, add static before a function or variable to make the function a static function. However, the meaning of "static" here is not the storage method, but the scope of the function is limited to this file (so it is also called an internal function ). Note that, whether static or not, external (global) variables are stored in the static storage area and the lifetime is global. at this time, static only applies to the scope, and the scope is limited within this module (file.
The advantage of using internal functions is that when different people write different functions, you don't have to worry about your own defined functions and whether they will have the same name as the functions in other files.
Example 3:
// File1.cpp
Static int Vara;
Int varb;
Extern void FUNA ()
{
......
}
Static void funb ()
{
......
}
// File2.cpp
Extern int varb; // use the global variable defined in file1.cpp
Extern int Vara; // error! Vara is static and cannot be used in other files
Extern vod funa (); // use the function defined in file1.cpp
Extern void funb (); // error! You cannot use the static function in the file1.cpp file.
Iii. static data member/member functions (C ++ exclusive)
C ++ has reused this keyword and given it a third meaning different from the previous one: to indicate variables and functions belonging to a class rather than any specific objects of this class. this is the biggest difference between a function and a common member function and its application. For example, when counting an object of a class, counting the number of instances of the class is generated, you can use static data members. static does not limit the scope or extend the lifetime, but indicates the uniqueness of variables/functions in this class. this is also the meaning of "variables and functions that belong to a class rather than any specific objects of this class. because it is unique for the entire class, it cannot belong to an instance object. (For static data members, whether the member function is static or not, there is only one copy in the memory. When calling a common member function, this pointer must be passed in. When calling a static member function, no this pointer .)
See example 4 (Copyright c ++ (2nd)> (copyright) page 1)
Class enemytarget {
Public:
Enemytarget () {++ numtargets ;}
Enemytarget (const enemytarget &) {++ numtargets ;}
~ Enemytarget () {-- numtargets ;}
Static size_t numberoftargets () {return numtargets ;}
Bool destroy (); // returns success of attempt to destroy enemytarget object
PRIVATE:
Static size_t numtargets; // object counter
};
// Class statics must be defined outside the class;
// Initialization is to 0 by default
Size_t enemytarget: numtargets;
In this example, the static data member numtargets is used to count the number of generated objects.
In addition, because the thread function pthread_create () in the POSIX database requires a global mechanism when designing multi-threaded operations, common member functions cannot be directly used as thread functions, you can use the static member function as a thread function. ============================ static class members include static data members and static function members.
A static data member:
When the static keyword is added before the declaration of the data member in the class body, the data member becomes the static data member of the class. Like other data members, static data members also comply with public/protected/private access rules. Static data members also have the following features:
1. Definition of static data members.
Static data members are actually global variables in the category. Therefore, the definition (initialization) of static data members should not be put in the header file.
The definition is the same as that of global variables. Example:
Xxx. h file
Class base {
PRIVATE:
Static const int _ I; // declaration, standard C ++ supports sequential type initialization in the class body, but vc6 does not.
};
Xxx. cpp File
Const int base: _ I = 10; // when defining (initialization), private and protected access is not restricted.
Note: do not try to define (initialize) static data members in the header file. In most cases, this will lead to repeated definitions of such errors. Not even if # ifndef # define # endif or # pragma once is added.
2. static data members are shared by all objects of the class, including objects of the derived classes of the class. That is, the derived class Object shares the static data member of the base class with the base class object. Example:
Class base {
Public:
Static int _ num; // Declaration
};
Int base: _ num = 0; // real definition of static data members
Class derived: public base {
};
Main ()
{
Base;
Derived B;
A. _ num ++;
Cout <"base class static data number _ num is" <A. _ num <Endl;
B. _ num ++;
Cout <"derived class static data number _ num is" <B. _ num <Endl;
}
// The result is 1 or 2. The derived class and the base class share a static data member.
3. The static data member can be an optional parameter of the member function, but not a common data member. Example:
Class base {
Public:
Static int _ staticvar;
Int _ var;
Void foo1 (INT I = _ staticvar); // correct. _ staticvar is a static data member.
Void foo2 (INT I = _ var); // error. _ VaR is a common data member.
};
4.★The type of static data members can be the type of the class to which they belong, whereas that of common data members is not. A common data member can only be declared as a pointer or reference of the class type. Example:
Class base {
Public:
Static base _ object1; // correct, static data member
Base _ object2; // Error
Base * pobject; // correct, pointer
Base & mobject; // correct, reference
};
5.★I don't know whether it is a feature in Standard C ++ or a feature of vc6.
The value of the static data member can be legally changed in the const member function. Example:
Class base {
Public:
Base () {_ I = 0; _ Val = 0 ;}
Mutable int _ I;
Static int _ staticval;
Int _ Val;
Void test () const {// const member function
_ I ++; // correct, mutable data member
_ Staticval ++; // correct, static data member
_ Val ++; // Error
}
};
Int base: _ staticval = 0;
2. static member functions
There is nothing to say about static member functions.
1. The address of the static member function can be stored by the common function pointer, while the common member function address needs to be stored by the class member function pointer. Example:
Class base {
Static int func1 ();
Int func2 ();
};
INT (* pf1) () = & base: func1; // common function pointer
INT (base: * pf2) () = & base: func2; // member function pointer
2. static member functions cannot call non-static members of a class. Because the static member function does not include the this pointer.
3. static member functions cannot be declared as virtual, const, and volatile functions at the same time. Example:
Class base {
Virtual static void func1 (); // Error
Static void func2 () const; // Error
Static void func3 () volatile; // Error
};
The last point is that static members can be accessed independently, that is, they can be accessed without creating any object instance.