1、生存周期和作用域的定义
生存周期:变量从定义到销毁的时间范围。
作用域:变量的可见代码区域(块作用域,函数作用域,类作用域、程序全局作用域),最常见的如:{}、static修饰符等等。
2、不同类型变量的生存周期和作用域
(1)全局变量
- 生存周期:从程序运行期一直存在,从程序开始到程序结束;
- 作用域:全局作用域(只需要在一个源文件中定义,就可以作用于所有的源文件);
- 引用方法:其他文件如果要使用,必须用extern 等关键字声明要引用的全局变量;
注意:如果再两个文件中都定义了相同名字的全局变量,则连接错误:变量重定义。
(2)局部变量
- 生命周期:程序运行处局部作用域,即被销毁。
- 作用域:局部作用域(只在局部作用于可见)
- 内存分布:栈区
- 定义方法:在局部作用域中用auto指示符定义,可省略auto
(3)静态全局变量
- 生命周期:程序运行期一直存在,从程序开始到程序结束;
- 作用域:文件作用域(只在被定义的文件中可见:static的一个作用就是隐藏)
- 内存分布:全局(静态存储区)。
- 定义方法:static关键字,const关键字(注意C/C++意义不同)
举个例子:
在文件A中定义了一个全局静态变量 a和一个全局变量b:
static int a = 1; //定义一个static
int b = 2; //默认为entern
它们的生存周期都是程序的整个运行期,但是b的作用域为全局作用域,可以通过extern在其他文件中使用,而a只能在文件A中使用,例如我们在文件B中:
extern int a; //error a在文件B中不可见
extern int b; //ok
int m = a; //error
int n = b; //ok 需要注意,这里有初始化先后顺序
也就是说,在声明全局的static变量时,static没有改变它的生存周期,也即存储位置(因为全局变量本来就存储在全局数据域),而是将变量的作用域限制在当前文件中。
(4)静态局部变量
- 生命周期:程序运行期一直存在;
- 作用域:局部作用域(只在局部作用域可见,超过其作用域便无法被引用)
- 内存分布:全局(静态存储区)。
- 定义方法:局部作用域中用static定义。
注意:只被初始化一次,多线程中需要加锁保护。
举个例子。在函数test中声明静态变量i:
void test()
{
int m = 3;
static int i = 5;
}
局部变量m存放在栈中,当test函数结束,m将被销毁;静态变量i不存放在栈中,而是存放于程序的全局变量区域,因此随着函数test的结束,它并不随着出栈操作而被销毁,它的生存周期存在于程序的整个运行期;然而m和i的作用域都仅存在于test函数中它们的定义之后,即test调用结束之后,m和i就不再可用,但是i仍存在于内存之中。
具体示例说明:
static int c = 1; //全局初始化区(静态全局变量)
int a = 0; //全局初始化区(全局变量)
char* p1; //全局未初始化区(全局变量)
int main(int argc, char const *argv[])
{
int b; //存放于栈区(局部变量)
char s[] = "abc"; //s存放于栈区(局部变量)
char* p2 ; //栈(局部变量)
char* p3 = "123456"; //p3存放于栈区(局部变量);“123456”存放区文字常量区
static int c = 0; //c存放于全局初始化区(静态局部变量)
p1 = (char*)malloc(10);
p2 = (char*)malloc(20); //分配得来的10和20字节的区域在堆区;
//变量p1、p2指向堆区分配的内存
strcpy(p1, "123456"); //“123456”存放区文字常量区
return 0;
}