0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何判定全局变量和局部变量

strongerHuang 来源:strongerHuang 作者:strongerHuang 2022-09-07 09:08 次阅读

何为变量?

变量一般可以细分为如下图:

7f0d0b24-2e45-11ed-ba43-dac502259ad0.png

本节重点为了让大家理解内存模型的“栈”,暂时不考虑“静态变量” 的情况,并约定如下:

“全局变量”仅仅默认为“普通全局变量”;

“局部变量”仅仅默认为“普通局部变量”。

如何判定全局变量和局部变量?

简单直观的来说,全局变量就是在函数外面定义的变量,局部变量就是在函数内部定义的变量,下面的例子能很清晰地说明全局变量和局部变量的判定方法:

unsigned char a;//在函数外面定义的,所以是全局变量。
voidmain()//主函数
{
 unsigned char b;//在函数内部定义的,所以是局部变量。
b=a;
while(1)
{

}
}

全局变量和局部变量的内存模型

单片机内存包括ROMRAM 两部分,ROM存储的是单片机程序中的指令和一些不可更改的常量数据,而 RAM存放的是可以被更改的变量数据;

也就是说,全局变量和局部变量都是存放在RAM,但是,虽然都是存放在 RAM,全局变量和局部变量之间的内存模型还是有明显的区别的。

因此,分了两个不同的RAM区,全局变量占用的 RAM区称为全局数据区, 局部变量占用的 RAM 区称为

它们的内存模型到底有什么本质的区别呢?

全局数据区就像你自己家的房间,是唯一的,一个房间的地址只能你一个人住(假设你还是单身狗的时候),而且是永久的(sorry),所以说每个全局变量都有唯一对应的 RAM 地址, 不可能重复的。

就像客栈, 一年下来每天晚上住的人不一样,每个人在里面居住的时间是有期限的,不是长久的,一个房间的地址一年下来每天可能住进不同的人,不是唯一的。

全局数据区的全局变量拥有永久产权,区的局部变量只能临时居住在宾馆客栈, 地址不是唯一的, 有期限的。

是给程序里所有函数内部的局部变量共用的,函数被调用的时候,该函数内部的每个局部变量就会被分配对应到的某个RAM 地址,函数调用结束后,该局部变量就失效。

因此它对应的 的RAM空间就被收回,以便给下一个被调用的函数的局部变量占用。

举例借用“宾馆客栈”来比喻局部变量所在的“栈”。

voidfunction(void);//子函数的声明

voidfunction(void)//子函数的定义
{
unsignedchara;//局部变量
a=1;
}

voidmain()//主函数
{
function();//子函数的调用
}

我们看到单片机从主函数 main 往下执行, 首先遇到function()子函数的调用, 所以就跳到function()函数的定义那里开始执行, 此时的局部变量 a 开始被分配在 RAM的“栈区” 的某个地址, 相当于你入住宾馆被分配到某个房间。

单片机执行完子函数function() 后,局部变量 a 在 RAM 的栈区所分配的地址被收回, 局部变量a 消失,被收回的RAM地址可能会被系统重新分配给其它被调用的函数的局部变量。

此时相当于你离开宾馆,从此你跟那个宾馆的房间没有啥关系, 你原来在宾馆入住的那个房间会被宾馆老板重新分配给其他的客人入住。

全局变量的作用域是永久性不受范围限制的,而局部变量的作用域就是它所在函数的内部范围。全局变量的全局数据区是永久的私人房子,局部变量的栈是临时居住的客栈。

总结如下

每定义一个新的全局变量,就意味着多开销一个新的RAM 内存。而每定义一个局部变量,只要在函数内部所定义的局部变量总数不超过单片机的栈区,此时的局部变量不开销新的 RAM内存, 因为局部变量是临时借用栈的, 使用后就还给栈,栈是公共区, 可以重复利用,可以服务若干个不同的函数内部的局部变量。

单片机每次进入执行函数时,局部变量都会被初始化改变,而全局变量则不会被初始化, 全局变量是一直保存之前最后一次更改的值。

有哪些常见疑问?

全局数据区栈区是谁在幕后分配的, 怎么分配的?

是C编译器自动分配的, 至于怎么分配,谁分配多一点,谁分配少一点,C 编译器会有一个默认的比例分配, 我们一般都不用管。

栈区是临时借用的,子函数被调用的时候,它内部的局部变量才会“临时” 被分配到“栈” 区的某个地址,那么问题来了,谁在幕后主持“栈区” 这些分配的工作?

单片机已经上电开始运行程序的时候,编译器已经不起作用,“栈区” 分配给函数内部局部变量的工作,确实是 C 编译器做的,但这是在单片机上电前。

C 编译器就把所有函数内部的局部变量的分配工作就规划好了,都指定了如果某个函数一旦被调用,该函数内部的哪个局部变量应该分到“栈区” 的哪个地址,C 编译器都是事先把这些“后事” 都交代完毕了才结束自己的生命。

等单片机上电开始工作的时候,虽然C编译器此时不在了,但是单片机都是严格按照C编译器交代的遗嘱开始工作和分配“栈区”的。因此,“栈区” 的“临时分配” 非真正严格意义上的“临时分配”。

函数内部所定义的局部变量总数不超过单片机的“栈” 区的 RAM 数量, 那, 万一超过了“栈” 区的 RAM数量, 后果严重吗?

这种情况专业术语叫爆栈。程序会出现莫名其妙的异常,后果特别严重。

为了避免这种情况, 一般在编写程序的时候, 函数内部都不能定义大数组的局部变量, 局部变量的数量不能定义太多太大,尤其要避免刚才所说的定义开辟大数组局部变量这种情况。

大数组的定义应该定义成全局变量,或者定义成 静态的局部变量

有一些C编译器,遇到“爆栈” 的情况,会好心跟你提醒让你编译不过去,但是也有一些 C 编译器可能就不会给你提醒,所以大家以后做项目写函数的时候,要对爆栈心存敬畏。

全局变量和局部变量的优先级

刚才说到,全局变量的作用域是永久性并且不受范围限制的,而局部变量的作用域就是它所在函数的内部范围。

那么问题来了,假如局部变量和全局变量的名字重名了,此时函数内部执行的变量到底是局部变量还是全局变量?

这个问题就涉及到优先级。

注意,当面对同名的局部变量和全局变量时,函数内部执行的变量是局部变量,也就是局部变量在函数内部要比全局变量的优先级高。

我们来举一些例子

请看下面第一个例子

unsignedchara=5;//此处第1个a是全局变量

voidmain()//主函数
{
unsignedchara=2;//此处第2个a是局部变量,跟上面全局变量的第1个a重名了
print(a);//把a发送到电脑端的串口助手软件上观察
while(1)
{

}
}

正确的答案是 2。在函数内部的局部变量比全局变量的优先级更加高。

虽然这里的两个a重名了, 但是它们的内存模型不一样,第1个全局变量的a是分配在全局数据区,是具有唯一的地址的,而第2个局部变量的a是被分配在临时的栈区的,寄生在 main 函数内部。

再看下面第二个例子

voidfunction(void);//函数声明
unsignedchara=5;//此处第1个a是全局变量

voidfunction(void)//函数定义
{
 unsigned char a=3;//此处第 2 个 a 是局部变量。
}

voidmain()//主函数
{
 unsigned char a=2;//此处第 3 个 a 也是局部变量。
function();//子函数被调用
print(a);//把 a 发送到电脑端的串口助手软件上观察。
while(1)
{
}
}

正确的答案是2。因为,function这个子函数是被调用结束之后,才执行 print(a)的, 就意味函数内部的局部变量(第2个局部变量 a)是在执行 print(a)语句的时候就消亡不存在了, 所以此时print(a)的a是第3个局部变量的a(在 main 函数内部定义的局部变量的 a)。

再看下面第三个例子

voidfunction(void);//函数声明
unsignedchara=5;//此处第1个a是全局变量

voidfunction(void)//函数定义
{
unsignedchara=3;//此处第2个a是局部变量
}

voidmain()//主函数
{
function();//子函数被调用
print(a);//把a发送到电脑端的串口助手软件上观察
while(1)
{
}
}

正确的答案是5。因为function这个子函数是被调用结束之后,才执行print(a)的,就意味function函数内部的局部变量(第2个局部变量)是在执行function(a)语句的时候就消亡不存在了。

同时,因为此时main函数内部也没有定义a的局部变量,所以此时function(a)的a是必然只能是第1个全局变量的a(在main函数外面定义的全局变量的a)。

最后

看到本文之后,相信大家已经对栈有了一些基础的认识,在嵌入式编程中,我们也要时刻注意,避免爆栈;如果有错误欢迎指出,我们下一期,再见。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储
    +关注

    关注

    13

    文章

    4257

    浏览量

    85648
  • 函数
    +关注

    关注

    3

    文章

    4303

    浏览量

    62411
  • 模型
    +关注

    关注

    1

    文章

    3158

    浏览量

    48701

原文标题:从嵌入式编程中感悟「栈」为何方神圣?

文章出处:【微信号:strongerHuang,微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    labview深入探索------全局变量局部变量与内存管理

    不存在全局变量和局部变量,同样可以编制规模很大的程序,这说明局部变量全局变量并不是必须的,LV提供了它们是因为在特定的情况下可以简化编程。当我们使用SUBVI时,我们需要定义一个连接
    发表于 07-13 17:49

    LabVIEW结构的使用——全局变量和局部变量

    全局变量和局部变量是LabVIEW用来传递数据的工具。LabVIEW编程是一种数据流编程,它是通过连线来传递数据的。但是如果一个程序太复杂的话,有时连线会很困难甚至无法连接,这时就需要用到局部变量
    发表于 02-09 14:46

    LabVIEW编程难点之局部变量全局变量

    最近学习Labview,找了3、4本书看,但是对局部变量全局变量的说法不是特别清晰,就此跟大家讨论下:Labview中局部变量是在一个VI中传递数据,如果说创建了前面板某个数值输入控件类型为
    发表于 01-08 20:46

    谨慎使用局部变量全局变量

    局部全局变量是高级的LabVIEW概念。它们不是LabVIEW数据流执行模型中固有的部分。使用局部变量全局变量时,程序框图可能会变得难以阅读,因此需谨慎使用。错误地使用
    发表于 01-30 10:58

    静态变量全局变量和局部变量

    域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern关键字再次声明这个全局变量。2>静态局部变量具有
    发表于 06-20 09:52

    【原创分享】STM32 C语言全局变量和局部变量

    作者:张角老师(张飞实战电子高级工程师)大家好,我们今天来探讨一下C语言的全局变量和局部变量。如果我们想彻底搞清楚这两个概念,我们必须回答几个问题:第一,C语言为什么要区分变量的作用域,或者说做出
    发表于 06-17 11:18

    全局变量和局部变量的相关资料推荐

    一些注意事项:全局变量和局部变量重名以后,根据就近原则,打印会显示局部变量的值,可在变量前加入::代表全部变量;应减少不必要的全部
    发表于 12-15 06:10

    编程时可以用局部变量替代全局变量

    尽量用局部变量替代全局变量。如果用局部变量能实现功能,最好用局部变量。在函数仅仅只是要用到某个全局变量,而无需改动时,就将
    发表于 02-28 06:22

    static作用(修饰函数、局部变量全局变量

    详细介绍了static作用(修饰函数、局部变量全局变量)的用法
    发表于 11-17 10:30 4次下载

    全局变量和局部变量有什么区别

    全局变量是编程术语中的一种,源自于变量之分。变量分为局部全局局部变量又可称之为内部
    发表于 12-11 11:58 3.2w次阅读
    <b class='flag-5'>全局变量</b><b class='flag-5'>和局部变量</b>有什么区别

    LABVIEW初级教程之局部变量全局变量的示例程序合集免费下载

    本文档的主要内容详细介绍的是LABVIEW初级教程之局部变量全局变量的示例程序合集免费下载
    发表于 01-16 10:23 34次下载
    LABVIEW初级教程之<b class='flag-5'>局部变量</b>与<b class='flag-5'>全局变量</b>的示例程序合集免费下载

    在C语言中,全局变量滥用的后果是什么

    01 啥是全局变量 说起全局变量,就不得不提到全局变量局部变量,静态全局变量,静态局部变量,这
    发表于 06-24 17:14 1641次阅读

    C语言中局部变量全局变量

    全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序。在函数中使用全局变量,一般应作全局
    的头像 发表于 10-15 10:48 5428次阅读

    详解LABVIEW中的局部变量全局变量

    本文档的主要内容详细介绍的是LABVIEW初级教程之局部变量全局变量的详细资料说明。
    发表于 03-29 15:00 26次下载

    Python-局部变量全局变量

    局部变量是在函数内部定义的变量,只能在函数内部使用,函数执行结束后,函数内部的局部变量会被系统回收,不同的函数,可以定义相同名称的局部变量,相互之间没有任何关联
    的头像 发表于 02-16 15:16 861次阅读
    Python-<b class='flag-5'>局部变量</b>与<b class='flag-5'>全局变量</b>