关于局部变量和静态变量(基于有一定指针基础)
#include<stdio.h>
void aaa()
{
int n=10;
}
int main()
{
printf("%d",n);
return 0;
}
在这个代码里,很明显会报错,未定义该n标识符,因为这个n是局部变量,只作用于这个函数里面,然后再来介绍一下标识符的作用域和生命周期:
某个标识符的生命周期表示这个标识符存在的周期,即在声明的代码块创建时开始,在改代码块结束时自动销毁,也就是会释放它所占的空间;
而标识符作用域即在它声明时开始,在该代码块结束时结束;
无论是变量还是加了const声明的常量都是一样;
而在这段代码里面就是在aaa函数开始创建时n的生命周期开始,在这个函数结束时自动销毁它即结束;它的作用域也就是在它声明时int n;开始,在这个函数结束时结束;所以它的作用域并没有走出这个函数,所以在主函数里面直接打印是不可以的;
不可以直接写,那么可以用函数返回它的指针(这样还不如直接返回它的值打印),然后在求出它的值,我之前就会这么写,现在想起来也是错误的:
#include<stdio.h>
int * aaa()
{
int n=10;
int* p = &n;
return p;
}
int main()
{
int* h = aaa();
printf("%d",*h);
return 0;
}
虽然结果是正确的,但是实际上是不可以的,由于这时候n的生命周期已经结束了也就是原本存在n的地址就会被释放,该地址就已经不存在了,这时候指向这个地址的指针就变成了野指针,野指针很容易奔溃,或者乱指向已经被被使用的地址,这样操作是不被允许的;
声明在代码块内的变量都是自动变量,也就是比如在代码块内定义的int类型,其实是 auto int类型,只不过可以省略;但是有时候就是需要一种变量来让他可以用到各个代码块里,这时候就有了另一种变量叫做静态变量,它的生命周期是在程序启动时创建,程序结束时销毁,也就是它的生命周期存在于整个文件。而且,静态变量除了有这个优点外,如果没有给变量赋值的话,就会自动赋值为零,数组也是;当然,在代码块外的任何变量都是静态存储类型的变量,且代码块的静态存储变量具有文件作用域,即在变量声明开始,到程序结束;
#include<stdio.h>
int n=10;
int main()
{
printf("%d",n);
}
当然,如果想要在代码块内定义静态变量也不是不可以在定义的类型上面加一个static(它的意思是静止的),这时候它的作用域仅在它声明时开始,到代码块结束时结束;
#include<stdio.h>
int* aaa()
{
static int n = 10;
int* p = &n;
return p;
}
int main()
{
int* h = aaa();
printf("%d", *h);
return 0;
}
这样写就是对的,也就是说这个n的生命周期是整个文件作用域,在代码块结束时虽然它的作用域结束,但是还存在,所以这时候它的地址也还在,所以可以这么操作;
而且,在代码外的变量如果也加了这个的话就可以以表示拒绝介入其他文件中,只在本文件有效(这样做的原因是为了在其他文件中用同样的变量但是不被重复定义):先看分别在三个文件的代码:
这里除了要打印人员函数外,主要是要看在两个文件里面分别定义了一个n,然后在主函数里面想打印主函数里的n,再用printPerson函数人员表的函数定义里的n打印出来;然后就会报错,错误是:
这是因为,文件作用域静态变量(也就是在代码块外的静态变量)也称为全局变量,多个源文件中不允许出现同名全局变量,这时候可以把把他们其中一个面前加一个extern(意为外部),并且去掉加了这个的赋值;这时候就可以了,也就是所有文件共享一个n,这时候打印的结果当然都是那个赋了的值;也就是说,如果我把主函数里面的int n=123;改为extern int n;这时候答应的就是另一个文件里面的456;
当然,如果我就是想按照原需求,打印不同的n怎么办呢,这时候就可以用到static,把它加到两个n的声明前面,这时候就行了;加了这个表示拒绝和其他文件共享本文件中的变量;
总结:作用域的大小和在代码块还是代码内有关,而生命周期和变量的存储类型有关,并不是所有的静态变量都叫全局变量;
---------------------------------------------------------------------------------------------------------------------------------
就算星星碎掉了溢出来的光也很好看。