我想你应该了解一些原则性的东西,这更好帮你理解
首先,一个总的原则是,c语言是面向效率的语言,它绝对不会初始化。也就是说,某个内存对应某个变量,这个无论是谁分配的,但是除非你赋值,否则它在分配以前存储的是什么,就是什么。这就是你说的“赋初值”。
然后要说的是,函数里面定义的局部变量,它存储在堆栈上,为什么要存储在堆栈上,因为函数是允许递归调用的,看下面的程序:
int sum(int n)
{
int result = 0;
if (n == 0) return result;
result = n + sum(n - 1);
return result;
}
在这个程序里,sum内部又调用了sum,显然,每次调用,都必须有一套独立的result变量的存储,如果只有一个result,那么程序就乱套了。
所以局部变量使用堆栈,每次调用的时候,自动开辟一个内存,将当前局部变量放上去,当函数调用结束,再自动回收这些内存,此时这个变量的地址就无效了。
这是为什么局部变量存在生命周期和不需要手工释放的原因。
全局变量显然只需要一套,你无论在哪个函数里调用,访问某个局部变量都是同一个,所以全局变量没有生命周期(或者说生命周期等于进程执行的时间)。既然全局变量只有一套,又是程序定义好的,所以在程序运行开始的时候就分配好了空间。但是记住我之前说的,c语言任何时候都不会初始化变量,因为初始化变量意味着要往这个内存地址里写入,而C语言不做不必要的事情。
关于作用域,我再补充说几句
C语言是一种比较原始的语言,上世纪70年代被设计出来,那个时候的计算机很糟糕,可能还没有你用的手表的运算能力强。因此那时候编写程序,没有什么IDE开发环境,甚至连一个全屏幕的编辑器都没有。
当很多人一起写程序,然后组合起来的时候,难免会遇到定义了同一个名字的不同变量的问题,这个问题很头痛,因为修改是困难的。C语言给出的变通的办法就是,允许重名的存在,比如
int a;
void foo()
{
int a;
...
}
此时局部变量和全局变量重名。那么究竟是认哪一个呢,在函数里,认局部变量a,这个叫做就近原则,在别的函数里,认全局变量a,因为在foo以外,别的地方看不到局部变量a,这就是作用域。
类似的
void foo()
{
if (...)
{
int a;
}
a = 123; //error
}
在函数里面的块定义的变量,出了块就不认。
注意作用域和生命周期没有关系。
生命周期结束,变量所在的内存无效。
作用域之外,只是说你代码不能访问到这个变量,但是不等于说这个变量存储的地方一定就无效了。