自动变量和静态变量的初始化存在一个重要的差别。在静态变量的初始化中,我们可以把可执行程序文件想要初始化的值放在当程序执行时变量将会使用的位置。当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给哪个变量。完成这个任务并不需要额外的时间,也不需要额外的只了能够,变量将会得到正确的值。如果不显式地制定其初始值,静态变量将初始化为0。自动变量的初始化需要更多的开销,因为当程序链接时还无法判断自动变量的存储位置。事实上,函数的局部变量在函数的每次调用中可能占据不同的位置。基于这个理由,自动变量没有缺省的初始值,而显式的初始化将在代码块的起始处插入一条隐士的赋值语句。
静态变量:其初始化值被放在程序执行时将使用的位置,所以不需额外时间,也不需额外指令。如果不显示初始化,静态变量将被初始化为0。
自动变量:程序链接时仍无法判断变量的存储位置。所以,自动变量没有缺省的初始值,而显示初始化将在代码的起始处插入一条隐式赋值语句。
这导致了四种结果:
- 自动变量初始化较之赋值语句效率并无提高。除了声明为const的变量之外,在声明变量的同时进行初始化和先声明后赋值只有风格只差,并无效率之别。
- 自动变量所在块每次执行时,都要对自动变量重新赋值。----这与静态变量大不相同,后者只是在程序开始执行前初始化一次。
- 由于初始化在运行时执行,因此可以使用任何表达式作为初始化值。(这也解释了为什么静态变量的初始化不能使用表式)
- 除非对自动变量显式初始化,否则当自动变量创建时,它的值一定是垃圾。
看下面的例题:
原文:http://blog.csdn.net/hanchaoman/article/details/8115073int a;
main()
{
while(1)
{
static b=1;
a=2;
b++;
a++;
}
}
我们所理解的静态变量b,只知道它在上面的函数内部只初始化一次,其实是个假像,我要表达的是,事实上b初始化的值,不是在循环体完成的.继续下看.
while(1)
{
static b=1;
a=2;
b++;
a++;
}
注意这一句:
static b=1;为什么我们循环体无限循环,b他只会赋一次值呢,从C上面是看不出来的.
经过我反汇编发现,
static b=1;根本不在循环体中.可以想像,程序被译成目标机器的时候是这个样子
while(1)
{
//static b=1; 这句没有!
a=2;
b++;
a++;
}
那么b是什么时候赋的值呢,是编译的时候就确定了。。就是说,编译的时候,就给b初始化好了!
类似,我们定义全局变量,如果不赋值,编译器给他赋上0.如果定义了值,就在编译的时候就确定下来了,这个值是编译器根据我们的语句赋给它的.而不程序中指令赋给它的!
那么这个a,b变量都在哪呢,他们呆在所谓的静态存储区(后面有介绍),物理上整个程序中任意代码都能访问到这片区域,说明他们在存储上是一样的.但是a,b区别又在哪呢,就是对他们的引用,编译器,允许你任何地方,函数中调用a,而b,不行,他有局部作用域,比如你在一个函数中声明了静态变量b,那只能在这函数中调用b.如果在其它的地方调用它,编译器会报错.这就是逻辑上的控制,而实际上,"物理"上是允许程序在任意地方访问b变量,但是编译器哥哥不会让你访问.
那什么又叫静态存储区呢,我个人认为就是这是安全区域,不会随便被别的变量替掉.分给你的就是你的,不会被别人给占了.
谈到这里我们顺便提一下,我们其它函数的局部变量存在内存中的位置,局部变量存放在栈中,栈是一片特殊内存区域,多个变量可能共享使用这片区域,这里我们就可以看到一个问题,既然共享使用,假如我们声明一个局部变量,如果不赋初值,这个变量所在栈中的位置,这个位置包含的值,是随机的,是上次别的变量留下来的值.