2021-5-10C语言变量的作用域和变量的存储类型for小白

本文对C语言的变量的作用域和变量的存储类型进行了简要说明,起到回顾功能。


前言

  • 为什么要尽量避免使用全局变量?
  • 编译器如何区分不同作用域的同名变量?
  • 编译器时如何给变量分配内存的?
  • 变量的存储类型有哪几种?
  • 变量的存储类型决定了什么?
  • 自动变量和静态局部变量有什么不同?

带着问题回顾

一、变量的作用域

  • 变量的作用域(Scope)
    变量的作用(能被读写访问的)范围
    取决于变量在源程序中被定义的位置
  • 局部变量(Local Variable)
    在语句块内(函数、复合语句)定义的变量
  • 全局变量(Global Variable)
    在所有函数之外定义的变量

特点:

  • 局部变量的作用域仅能在定义他的语句块(包括其下级语句块内)访问
  • 局部变量的作用域作用域较小的局部变量隐藏作用域较大的局部变量
  • 全局变量的作用域从定义变量的位置开始,到本程序结束。
  • 局部变量与全局变量同名,局部变量隐藏全局变量,互不干扰。
  • 形参与全局变量同名,局部变量隐藏全局变量,互不干扰。
  • 并列语句块内的局部变量同名,互不干扰,形参值改变不影响与其同名的实参值。

小结一下:

  • 只要同名的变量出现在不同的作用域内,二者互不干扰,编译器有能力区分不同作用域中的同名变量。
  • 如果同名变量出现在同一个作用域中,编译器无法区分,编译器只能区分不同作用域的同名变量。

编译器是如何区分不同作用域的同名变量呢?

  1. 编译器通过将同名变量映射到不同的内存地址来实现作用域的划分
  2. 局部变量和全局变量被分配的内存区域不同,(局部变量被分配到动态存储区,全局变量被分配到静态存储区)因而内存地址也不同。
  3. 形参和实参的作用域、内存地址不同,所以形参值的改变不会映像到实参。

最开始的两个问题:
全局变量有什么用?
当多个函数必须共享同一个固定类型的变量时。
当少数几个函数必须共享大量数据时。

但是全局变量是有副作用的。

  • 它破坏了函数的封装性,不能实现信息隐藏。
    谁都可以改写它,很难确定谁改写了它
  • 依赖全局变量的函数很难在其他程序中复用
    依赖全局变量的函数不是“独立”的
  • 对于使用全局变量的程序,维护起来比较困难。
  • 建议在可以不用时尽量不用
    多数情况下,通过形参和返回值进行数据交流比共享全局变量的方法更好。

二、变量的存储类型

C程序的内存映像

在这里插入图片描述

  • 只读存储区
    存放机器代码和常量等只读数据
  • 静态存储区
    存放程序中的全局变量和静态变量等。
    静态指的是发生在程序编译或链接时。
  • 动态存储区
    包括堆和栈。其中,栈用于保存函数调用时的返回地址、函数的形参、局部变量等信息。
    动态指的是发生在程序载入和运行时

变量的存储类型觉得变量放在静态存储区还是动态存储区。

  • 变量的存储类型
    编译器位变量分配内存的方式
    决定了变量的生存期(Lifetime)
  • 在静态存储区中分配内存的变量
    生存期是整个程序,全程占据内存
  • 在动态存储区中分配内存的变量
    生存期是定义它的语句块

所以说:静态存储区中的变量:与程序“共存亡”
动态存储去中的变量:与语句块“共存亡”

声明变量的存储类型

  • 声明变量的存储类型
    存储类型 数据类型 变量名;
  • C存储类型关键字
    auto(自动变量)
    static(静态变量)
    extern(外部变量)
    register(寄存器变量)

如果在所有函数外部没有指明其存储类型的话,他就是一个外部变量,外部变量也是一个全局变量。

全局变量和外部变量

在静态存储区内分配内存
其生存期是整个程序的运行期
没有显式初始化的外部变量由编译程序自动初始化为0
在整个程序运行期间,在定义它的位置到本文件的末尾,都可以访问它。但如果想要在其他文件中进行访问、或者在定义点之前访问,那么就要将它声明为外部存储类型。
extern 数据类型 变量名;
编译器并不对其进行分配内存,只是表明“我知道了”
因此对于外部变量,他的定义和他的声明是不一样的。

自动变量和静态局部变量
  • 自动变量——动态局部变量(缺省类型)
    auto 数据类型 变量名;
    auto指进入语句块时自动申请内存,推出时自动释放内存,离开函数,值就消失。
  • 静态变量
    static 数据类型 变量名;
    static从程序运行器占据内存,程序退出时释放内存。离开函数,值仍保留。
    静态存储区便align编译时自动初始化为零,仅初始化一次。
    静态变量包括:静态局部变量(一个语句块内定义static)和静态全局变量(所有函数外部定义static)。
    静态变量包括两种:静态全局变量和静态局部变量,他们唯一的区别是,他们的作用域不同。静态局部变量是在一个语句块内,静态全局变量是在一个文件内。但是由于他们都是静态变量都是在静态存储区中分配内存的,因此他们的生存期都是相同的都是从程序的运行开始到结束。
寄存器变量
  • 寄存器变量的生存期与程序“共存亡”
    register 类型名 变量名;
    在这里插入图片描述
    适用于使用频率较高的变量,可使程序更小、执行速度更快。
    现代编译器有能力自动把普通变量优化为寄存器变量,且可以忽略用户的指定。因此咱们写不写。。。都一样。编译器不管你。。。
    一般就不需要特别声明变量为register了。

最后一张图片作为总结:
在这里插入图片描述


总结

感谢苏老师
冬天不戴帽子 冻脑筋

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值