目录
局部变量和全局变量
局部变量
全局变量
小考点
静态局部变量和静态全局变量
需求
内存分区
静态局部变量
静态全局变量
大家好啊!欢迎来到我的博客,这里是困了电视剧,今天我准备和大家一起学习一下变量的相关知识,同时为函数知识打一个铺垫,在一段时间后,我会把函数的详解给大家肝出来,关注我不迷路哦!废话少说,让我们开始今天的学习吧!
在介绍变量之前,我们得引入一个重要的概念——变量的作用域和生命周期。
作用域是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
以变量举例:局部变量的作用域是变量所在的局部范围,全局变量的作用域是整个工程。
这时候可能有同学会问了,局部范围和整个工程是什么意思,具体指哪些?我们来上段代码一探究竟。先说局部范围。
#include
void print() {
printf("%d", num1);
}
int main() {
int num1 = 10;
{
int num0 = 1;
printf("%d", num0);
printf("%d", num1);
}
printf("%d", num0);
printf("%d", num1);
return 0;
}
现在我们对这段代码进行编译。
我们可以清晰地看到,程序报错了,看一下原因发现是因为我们在第18行和第26行使用了未定义的标识符,这说明什么,说明我们在main函数中定义的num1,print函数中无法使用,我们在main函数{}中定义的num0,除main函数的内部的那个{}外,其他地方无法使用,不过main函数内部的{}中却可以使用num1这个变量。
这时候,有些聪明的同学可以看出来,这个“局部范围”听起来挺高大上的,其实不就是用{}括起来的范围嘛,没错,对于局部变量来说,他的局部范围就是他所在的{}中的范围。所以对于局部变量来说,其生命周期也与其所在的局部范围相关,当程序运行到局部变量的局部范围时,其生命周期开始,当程序的运行到局部范围之外时,其生命周期也就结束了。
理解了局部变量后,我们现在来看看全局变量。
#include
//定义在函数外部的变量是全局变量
int num1 = 10;
void print() {
printf("print函数中的num1:%d", num1);
}
int main() {
int num2 = 20;
printf("main函数中的num1:%d\n", num1);
printf("main函数中的num2:%d\n", num2);
print();
return 0;
}
运行结果如图:
我在函数外部定义了一个全局变量num1,同时我又在main函数中定义了一个局部变量num2,可以看到num1不论是在main函数中还是在print函数中都可以使用,但“整个工程”仅仅指的就是这一个源文件吗,我们来看一个有趣的东西。
我创建了两个源文件,一个是域1,一个是域2,我在域1中声明了一个全局变量并把我域1中的main函数给注释掉,现在让我们看一下域2
我在域2中用extern关键字先对num1进行一个声明,然后我把num1给打印出来
我们可以发现我没有在域2源文件中进行任何赋值,但他却输出了我在域1中赋的值,并且我还能在域2中对num1这个变量进行修改,这就是全局变量,即我可以在一个project中的任何地方对这个全局变量进行使用和修改!其生命周期是贯穿程序始终的,即,只有当程序运行完毕后,其生命周期才会结束。
小考点来了,请同学们看下段代码:
#include
int num = 1;
int main() {
int num = 2;
printf("%d", num);
return 0;
}
C语言允许局部变量和全局变量同名,那当发生这种情况时,程序会怎样取用?
这里,程序会让局部变量屏蔽全局变量,其运行结果如下:
那么新的问题来了,全局变量能让所有源文件都可以使用和修改这个变量,在方便的同时他必然会带来一个问题,那就是他会使这个变量的安全性降低,毕竟谁都有权限修改这个变量嘛,那如果这个变量是很重要的变量呢?重要到不能轻易的修改但程序员在编写这个源文件时又需要在这个源文件中的任意地方使用怎么办?
我们知道全局变量不仅是创造该变量的源文件可用,同时其他源文件也可用,程序员们为了让一个变量仅在创造这个变量的源文件可用而其他源文件不可用,于是创造了静态局部变量和静态全局变量的概念。
在了解静态变量之前我们先了解另一个概念——内存分区。
在c/c++中,可以将内存划为四大内存分区,即栈区,堆区,静态区和只读区,他们可以粗略的理解为:栈区用来存放局部变量和函数的参数等,堆区用来存放动态分配的内存等,静态区用来存放静态变量和全局变量等,而只读区又分为两个部分,一个是常量区,一个是代码区,常量区用来存放我们声明的常量,而代码区用来存储我们写的代码。
局部变量前用static修饰就会变成静态局部变量,此时这个变量就会从原本的栈区转移到静态区,其生命周期就和全局变量一样和整个程序相同。全局变量前用static修饰就会变成静态全局变量。现在,上代码!
#include
void print() {
int num = 0;
num += 1;
printf("%d\n", num);
}
int main() {
int i = 0;
for (i = 0; i < 5; i++) {
print();
}
return 0;
}
print函数中的num是一个局部变量,其运行结果:
现在我们在num加一个static修饰:
#include
void print() {
static int num = 0;
num += 1;
printf("%d\n", num);
}
int main() {
int i = 0;
for (i = 0; i < 5; i++) {
print();
}
return 0;
}
其运行结果为:
同学们,发现了吗,这就是改变生命周期的结果。不过,也仅仅是改变了生命周期,其局部范围并没有改变,仍然局限在他所属的{}内
最后,让我们了解一下静态全局变量,还是,上代码!
我们可以看到在域1中num可以在两个函数中使用,在域2,也可以进行相应的修改和使用。现在我们在num前面加一个static进行修饰。
我们看到此时域2就无法使用num这个变量,但是num在域1这个源文件中仍可以像“全局变量”一样,在不同函数中使用,就比如下段代码:
#include
static int num = 0;
void add() {
num += 1;
}
void mul() {
num *= 2;
}
int main() {
add();
mul();
printf("%d", num);
return 0;
}
其运行结果为:
这就是静态全局变量,由此,程序员们用局部变量,全局变量,静态局部变量,静态全局变量实现一个project中所有位置的权限细分。