keil C51局部变量不释放?

[复制链接]
11074|27
手机看帖
扫描二维码
随时随地手机跟帖
W_Controller|  楼主 | 2013-1-11 13:57 | 显示全部楼层 |阅读模式
keil对C51的局部变量进行了覆盖,当一个函数定义了一个局部变量时,这个变量不会像标准C一样随着函数调用完之后收回内存,销毁变量,而是一直不释放,生存期是整个程序的运行时间。如果真的是这样,为什么我写的测试程序却得不到想要的效果呢?
程序大概是这样:
int tmp;
if(key == 0)
{
       tmp++;
}
return tmp;
即当我按下按键时,要求得到的局部变量加1,可是这个变量却不会一直加,非要我在int tmp 之前加上关键字static时,这个变量才不释放,才会储存之前的值,使得按键按下一次加一的效果。
希望大侠帮我讲解一下,究竟keil对局部变量是如何处理的?为什么我这里的代码没有得到“不释放”的效果?

相关帖子

原野之狼| | 2013-1-11 14:05 | 显示全部楼层
“keil对C51的局部变量进行了覆盖,当一个函数定义了一个局部变量时,这个变量不会像标准C一样随着函数调用完之后收回内存,销毁变量,而是一直不释放,生存期是整个程序的运行时间。”

请问这句话的出处在哪里?

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
lzqxs89 + 3 很给力!
liusensen| | 2013-1-11 14:58 | 显示全部楼层
不清楚

使用特权

评论回复
dirtwillfly| | 2013-1-11 16:02 | 显示全部楼层
建议楼主尽量找一些官方的资料来看,有些网上的资料不能全信的。

使用特权

评论回复
ayb_ice| | 2013-1-11 16:06 | 显示全部楼层
局部变量是可以被覆盖的,多个函数共用的(函数之间不会相互调用,不管是直接的还是间接的),地址是固定的,

使用特权

评论回复
bruceding| | 2013-1-11 17:06 | 显示全部楼层
局部变量是放在栈区的,函数返回时就释放了。要想不释放就是静态区了,全局变量或静态变量。

使用特权

评论回复
W_Controller|  楼主 | 2013-1-11 18:30 | 显示全部楼层
原野之狼 发表于 2013-1-11 14:05
“keil对C51的局部变量进行了覆盖,当一个函数定义了一个局部变量时,这个变量不会像标准C一样随着函数调用 ...


https://bbs.21ic.com/forum.php?mod=viewthread&tid=401289

使用特权

评论回复
W_Controller|  楼主 | 2013-1-11 18:31 | 显示全部楼层

使用特权

评论回复
xyz769| | 2013-1-11 23:14 | 显示全部楼层
  找本C语言基础书看看吧。

使用特权

评论回复
huangxz| | 2013-1-11 23:52 | 显示全部楼层
W_Controller 发表于 2013-1-11 18:31
再看下面的链接
http://blog.csdn.net/zhbsniper/article/details/7179316

楼主这个post讲的很清楚哦,覆盖是不同的function共享内存,这与你要求的不是一个概念。你那个叫独占,是静态变量的概念。

使用特权

评论回复
linqing171| | 2013-1-12 08:39 | 显示全部楼层
本帖最后由 linqing171 于 2013-1-12 08:43 编辑

51没有单独的堆指针。只有一个sp给了栈了,没有办法上世纪七十年代的架构。
keil为了代码效率,固定的函数的固定变量,在堆的位置是固定的,生成的代码是绝对地址访问。
A调用A1,A2;
其他函数均没有调用A11,A12
假设A里面有x个局部变量,A1里面有x1个局部变量。A2里面有x2个局部变量。那么x1个变量和x2个变量的地址是复用的,他们在堆上的同样的地址。

另外,堆区的释放是指逻辑上的变量生存周期已经结束了,除非被后面调用的函数的变量给覆盖,否则还是在那个内存里的。比如你的使用的最深的那个变量,也就是整个项目里面地址最大的那个栈位置的临时变量,肯定会一直伴随着你的系统生命周期都存在。而在main函数里面的临时变量也是永远都在的。


IAR有三种编译模式,有一种传递参数都是通过 “寄存器+栈” 传递,还有一种是 “寄存器+堆” 传递。而keil参数少的时候是寄存器,多到一定的程度后就是“寄存器+栈”方式。当局部变量(包含它所调用的所有函数)非常少的时候,也不用堆,而用寄存器。

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
W_Controller + 3 赞一个!
linqing171| | 2013-1-12 08:45 | 显示全部楼层
楼主可以学一下 编译原理的 基础,编译器的 手册、帮助 里面也有。

使用特权

评论回复
江枫渔火| | 2013-1-12 09:17 | 显示全部楼层
加上关键字static,这是正确用法。首先不说你那个KEIL的说法是不是正确的,但从代码的可读性,可理解性,规范性,你就不应该使用非C语言标准用法,除非万不得已,或有显著作用。

使用特权

评论回复
lyn3210| | 2013-1-12 09:54 | 显示全部楼层
改变优化等级为4级以上。

使用特权

评论回复
原野之狼| | 2013-1-12 11:40 | 显示全部楼层
linqing171 发表于 2013-1-12 08:39
51没有单独的堆指针。只有一个sp给了栈了,没有办法上世纪七十年代的架构。
keil为了代码效率,固定的函数 ...

请问一下  
“寄存器+堆”传递  
是怎么回事呢?

使用特权

评论回复
原野之狼| | 2013-1-12 11:41 | 显示全部楼层
楼主可以就KEIL的覆盖技术找点资料来加深一下理解

使用特权

评论回复
明月小厨| | 2013-1-12 13:48 | 显示全部楼层
楼主的理解上对的;局部变量就是在局部生存;
{
int tmp;//没有初始化为=0;同时没有定义它为无符号数(也许差别很大,导致效率大减)
if(key == 0)
{
       tmp++;
}
return tmp;
}
//关键的问题是程序有可能会优化.会不会是被优化掉了呢?
//假设你初始化tmp=0;则......
//运行的结果返回值是 (key==0),tmp根本不需要存在;
//如果定义为static,编译器一时判断不出tmp是不是垃圾变量,放你一马.

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
W_Controller + 3 赞一个!
W_Controller|  楼主 | 2013-1-12 15:48 | 显示全部楼层
江枫渔火 发表于 2013-1-12 09:17
加上关键字static,这是正确用法。首先不说你那个KEIL的说法是不是正确的,但从代码的可读性,可理解性,规 ...

嗯。我这里主要是为了测试keil对局部变量存储机制

使用特权

评论回复
W_Controller|  楼主 | 2013-1-12 15:49 | 显示全部楼层
lyn3210 发表于 2013-1-12 09:54
改变优化等级为4级以上。

真的是优化问题,我把优化等级改为0便有了效果

使用特权

评论回复
W_Controller|  楼主 | 2013-1-12 15:58 | 显示全部楼层
明月小厨 发表于 2013-1-12 13:48
楼主的理解上对的;局部变量就是在局部生存;
{
int tmp;//没有初始化为=0;同时没有定义它为无符号数(也许差 ...

1、确实是优化问题,优化等级改为0便有了效果;
2、贴出的那段代码是临时写的,目的只是用来测试keil对局部变量的存储机制,并没有考虑效率问题。呵呵,大侠见笑了;
3、如果我初始化为0,那肯定是没有得到我想要的效果了;这样每次进入函数时都会被初始化为0(没有存储上次的结果),我想,这也是与加上关键字static的区别吧,因为就算keil不会对局部变量进行释放,但是每次进入函数时还是会初始化的,若加上static,那只有初始化一次,下次调用不会被初始化了;
不知道我说的对不,还请大侠指点

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

169

帖子

0

粉丝