目录

【飞郁2022新课程】20 - 局部变量和全局变量

[在前面的课中 我们讲了常量和变量

这里我们讲下变量的作用域 和 局部变量 全局变量 全局静态变量 局部静态变量

在讲到这些之前 还需要了解下程序的内存分配问题

一、程序的内存分配

一个由C/C++编译的程序占用的内存分为以下几个部分:

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放

4、文字常量区 — 常量字符串就是放在这里的。 程序结束后由系统释放。

5、程序代码区 — 存放函数体的二进制代码。

好了进入正题!

二、作用域

接下来我们讲到的第一个 是作用域

首先还是从字面意思去理解 因为遇到一个专用名词 其字面意思 肯定或多或少能体现出其功能的特性

好了废话不多说

1.首先作用域关键在于一个"域"字的体现

2.联想到了“区域”“范围”等词

3.通俗点来讲就是 对变量限制了作用范围

4.这里首先介绍下 { } 花括号 ,这个就是用来限制齐变量的作用范围的

5.想必大家在之前的代码中 就有所接触到了

由于这里作用域不能单方面的用代码去体现出其作用 我们还需要配合以下知识点去配合讲解

所以开始讲第二个知识点 局部变量

三、局部变量

main函数 中{} 我们之前定义的变量 就限制在这个区域中.

如果出了这个区域 变量申请的内存控件就被系统回收了—称为局部变量.

void main() { int a=1; }

看下比较官方的介绍:

局部变量也只有局部作用域,它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。

四、 全局变量

简单来讲,把整个程序的运行周期作为一个限定变量的有效区域 —称为全局变量.这种是不需要{}来说明作用域,如果不初始化则会自动初始化为0.当程序结束.这些变量才会被系统回收.

看下比较官方的介绍:

全局变量具有全局作用域.全局变量只需在一个源文件中定义,就可以作用于所有的源文件.

当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量.

extern 在之前讲常量和变量提及到过

4.1 例如

a.cpp

#include “b.h” int g_a=1; void main() { Test(); printf(“g_a=%d\n”,g_a); }

b.h

void Test();

b.cpp

int g_a=1; void Test() { g_a=2; }

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/fa2b8dee282de6282501c3851ba431cc6f8e6ecc.png@942w_135h_progressive.png

编译出现错误

原因:对同一个变量名多重定义了,因为g_a是全局变量,那么怎么引用同一个变量呢?

之前讲过,使用extern.我们改进下.

b.cpp源文件使用extern

extern int g_a;//只需要声明一次就行了 .

申明之前也讲过,表示告诉编译器 我们这个变量在别的文件中被定义过了 切记!!

b.cpp

extern int g_a; void Test() { g_a=2; }

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/cf167aa8ff997ced09b1cdf251b9ff782e6a039b.png@590w_162h_progressive.png

五、全局静态变量

和上面的全局变量同理 但是是限制变量在定义这个变量的源文件中

看下比较官方的介绍:

静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。

a.cpp文件

static int g_a=1; void main() { Test(); printf(“a.h => g_a=%d\n”,g_a); }

b.cpp文件

static int g_a=1; void Test() { g_a=2; printf(“b.h => g_a=%d\n”,g_a); }

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/ef88bbee7f3fa6d792a74a5bc051e88e53248fe5.png@584w_153h_progressive.png

发现编译成功! 因为是全局静态变量 他们被限制在了 被定义的文件中

说明这2个变量虽然名字一样 但是是不同的变量 因为他们的内存地址就不是同一个 切记!!!

六、局部静态变量

上面讲到过局部变量是用{}来限制作用域的,同时这个局部静态又多了一个静态的属性,到底是什么意思呢?

静态变量的含义就是把变量放在静态区, 同时又用{}限制了作用域.

也就是说如果没有静态属性,局部变量本应该离开{}限制的作用域后就会释放变量,但是这里多了一个静态属性就不会释放,当多次调用相同函数的时候这个变量会一直存在,所以这个变量就从原来拥有释放变量的功能从而变成了这个局部静态变量只能在这个{}作用域内被引用.

我们看看下面的例子就明白了

void add(int a,int b) { static int c = 0;//局部静态变量 c=a + b + c; printf(“c=%d \n”,c); } void main() { add(1, 2); add(2, 3); }

观察结果

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/0ec8af979485866053e71b35cb8d07b24fdfa8e2.png@584w_146h_progressive.png

第一次调用add()函数的时候变量c等于3,当第二次调用add()函数的时候变量c由于第一次调用被赋值等于了3,所有会从3开始,也产生了3+2+3=8的结果