1. 本地变量/局部变量
1.1 本地变量/局部变量是什么?
在大括号内定义的变量就是本地变量/局部变量。
1.2 本地变量/局部变量有什么特点?
- 本地变量是定义在代码块内的,可以定义在函数的块内,可以定义在语句的块内。
for(int i=0;i<10;++i){
printf("%d ",i);
}
printf("%d ",i);
可以定义在一个随意的大括弧里面。
{
int n = 0;
printf("%d ",n);
}
printf("%d ",n);
- 程序进入块前,内部变量不存在,离开时失效。
- 块外定义的变量,块内仍然有效。
函数的每次运行,都会产生一个独立的变量空间,在这个空间中的变量,是函数这次运行独有的。
- 定义在函数内部的变量就是本地变量
- 参数也是本地变量
1.3 本地变量/局部变量初始化
- 本地变量不会默认初始化
- 参数在进入函数时被初始化。
本地变量/局部变量的生存期和作用域都是在大括号内。
2. 全局变量
2.1 全局变量是什么?
定义在函数外面的变量称为全局变量
int n;
int main(){
int m;
printf("n=%d\m=%d\n",n,m);
}
2.2 全局变量有什么特点?
全局变量有全局的生存周期和作用域。
- 不属于任何函数。
- 所有函数内部都可以使用。
int n;
int func(){
printf("in func n = %d\n",n);
// n = n*2;
}
int main(){
scanf("%d",&n);
func();
printf("in main n = %d\n",n);
}
2.3 全局变量初始化
- 没有初始化的全局变量会自动初始化为
0
。 - 只能用编译时刻已知的值初始化全局变量。
- 初始化发生在
main()
前。
int n = 2;
int m = n;
double s = sqrt(n);
int main(){
printf("n = %d,m = %d,s = %f",n,m,s);
}
2.4 同名隐藏
如果函数内部存在与全局变量同名的变量,则全局变量被隐藏。
int n = 10;
int main(){
int n = 1;
printf("n = %d\n",n);
}
3. 全局静态变量
3.1 全局静态变量是什么?
在全局变量前加上关键字static
。
static int n;
int main(){
int m;
printf("n=%d\m=%d\n",n,m);
}
3.2 全局变量与全局静态变量区别
- 若程序由一个源文件构成时,全局变量与全局静态变量没有区别。
- 若程序由多个源文件构成时,全局变量与全局静态变量不同:全局静态变量使得该变量成为定义该变量的源文件所独享,即:全局静态变量对组成该程序的其它源文件是无效的。
- 具有外部链接的静态,可以在所有源文件里调用,除了本文件,其他文件可以通过
extern
的方式引用。
4. 本地静态变量
4.1 静态本地变量是什么?
在本地变量定义时加上static
变成静态本地变量。
4.2 静态本地变量有什么特点?
当函数离开时,静态本地变量会继续存在并保存其值。
int inc(){
static int n = 1;
n = n + 1;
return n;
}
int main(){
printf("%d\n",inc());
printf("%d\n",inc());
printf("%d\n",inc());
}
静态本地变量的初始化在第一次进入函数时执行,以后进入函数会保持离开的值。
静态本地变量是特殊的全局变量,具有全局生存周期和局部作用域。
5. 总结
5.1 变量的作用域和生命期
- 作用域
变量或函数在运行时候的 有效作用范围 。 - 生命期
变量或函数在运行时候的没被销毁回收的存活时间。
No. | 分类 | 作用域 | 生命期 |
---|---|---|---|
1 | 局部变量 | 所在代码块内 | 所在函数结束 |
2 | 全局变量 | 所有文件内 | 程序执行结束 |
3 | 静态局部变量 | 所在代码块内 | 程序执行结束 |
4 | 静态全局变量 | 当前文件内 | 程序执行结束 |
5 | 普通函数 | 所有文件内 | - |
6 | 静态函数 | 当前文件内 | - |
6. static
关键字小结:
static
在C语言里面既可以修饰变量,也可以修饰函数。
-
static
变量:静态局部变量:在函数中定义的,生命周期是整个源程序,但是作用域和局部变量没区别。
只能在定义这个变量的函数范围内使用,而且只在第一次进入这个函数时候被初始化,之后的初始化会跳过,并保留原来的值。退出这个函数后,尽管这个变量还在,但是已经不能使用了。-
静态全局变量:全局变量本身就是静态存储的,但是静态全局变量和非静态全局变量又有区别:
- 全局变量:变量的作用域是整个源程序,其他源文件也可以使用,生命周期整个源程序。
- 静态全局变量:变量的作用域范围被限制在当前文件内,其他源文件不可使用,生命周期整个源程序。
static
函数(内部函数):
只能被当前文件内的其他函数调用,不能被其他文件内的函数调用,主要是区别非静态函数(外部函数)。
不对外公开的函数和全局变量
在函数前面加上static
就使它成为只能所在编译文件中使用的函数。
在全局变量前加上static
使它成为只能所在编译文件中使用的全局变量。
7. 最佳实践
7.1 不要返回本地变量的指针
- 返回本地变量的地址是危险的。
- 返回全局变量或静态本地变量的地址是安全的。
- 返回函数内的动态内存是安全的,但注意要记得释放。
- 最好的做法是返回传入的指针。
7.2 慎用静态变量
不要使用全局变量在函数间传递参数和结果。
尽量避免使用全局变量。
使用全局变量和静态本地变量的函数是不可重入的,是线程不安全的。
- 如何解决返回局部数据的问题?
#include <stdio.h>
#include <stdlib.h>
void print_array(int arr[],int n){
for(int i=0;i<n;++i){
printf("%d ",arr[i]);
}
printf("\n");
}
int* scanf_array(int* n){
scanf("%d",n);
int* arr = (int*)malloc(*n*sizeof(int));
for(int i=0;i<*n;++i){
scanf("%d",&arr[i]);
}
return arr;
}
int main(){
int n;
int *arr = scanf_array(&n);
print_array(arr,n);
free(arr);
}