BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #87201同步于 2015/5/23
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

[问题]局部变量在内存中的分布问题

yunwu
2015/5/23镜像同步22 回复
昨天看书的时候脑子一抽,突然想到一个问题:函数中的定义的局部变量存储在栈空间中,存储过程中是从高地址向低地址压栈。那么如果定义两个整形变量i、j,他们的地址肯定是连续的,取得一个变量的地址,也就能求得另一个变量的地址,从而可以对另一个变量操作。 逻辑上说得通,但是操作中遇到了这么奇怪的问题: 先打印出i和j的地址,然后再根据指针打印变量的值,可行。 把打印地址的语句注销掉,不可行。。。。 有点醉,难道打印地址那条语句还有其他的功能吗?或者是编译器的问题?或者是语言的问题?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
yunwu机器人#1 · 2015/5/23
大家忽略第一行的123456789 56789吧,那是我测试strcpy函数的输出。。。。
hh1562535601机器人#2 · 2015/5/23
下次发代码,别发图。 你说的这些都是由具体实现决定的,标准不保证这些行为。我用DevC++运行你第二个程序输出2 1
nuanyangyang机器人#3 · 2015/5/23
“函数中的定义的局部变量存储在栈空间中,存储过程中是从高地址向低地址压栈。”这个叙述是错的。 c语言对变量在哪里存储没有规定。把指针移出一个变量的存储范围的意义就是什么都可以发生,从什么都不发生到机器冒烟都可以。 来自「北邮人论坛手机版」
xionger机器人#4 · 2015/5/23
书本上说的没有错,局部变量是在栈中分配,栈也是从高到底。 但是不同的C++编译器实现的不一样,我用gcc 4.4.7你的代码是可以正确的,输出1。 我用vs2010中的c++编译器,i,j地址的差值不是1,而是3,我用cout<<*(p+3)就可以输出,编译器不一样可能结果不同,这只是在我的机器上是这样。 书本上的原理是正确的,只是编译器在做的时候要考虑很多东西,比如什么内存对齐、优化等等之类的,可能会有出入。 另外,你的这种情况,注释的那句话产生了这种情况我没遇见,可能是你的编译器优化不一样,不知道具体的情况,要是你能贴上汇编的代码比较好。会不会是你的编译器对常量折叠做的比较狠,像 i 一直没有被赋值和使用地址,就作为常量折叠了,导致内存里不分配。然后注释的那句话,使用了i的地址,导致编译器强制分配内存,然后内存里就有i了。 当然这只是猜测。[ema11] 尽量不要去假设编译器会怎么做,它可能比我们想的还要好。 要是想自己玩内存操作,还是用汇编吧,c和c++毕竟还是不好直接操作的。
LafengHu机器人#5 · 2015/5/23
谁教你这么写代码的[ema1] 【 在 yunwu 的大作中提到: 】 昨天看书的时候脑子一抽,突然想到一个问题:函数中的定义...
sxy0322机器人#6 · 2015/5/23
很简单。你没用到i,编译期自动优化,就当你没写过那个语句。 建议在gcc下不使用优化看效果。或者vs下debug模式运行后看效果,不排除不同版本也进行优化的可能。理论上你的想法是对的。
nickluchen机器人#7 · 2015/5/23
没怎么仔细看上边别人的回复,可能有人已经提到了。 你的第二段code很有可能被编译器优化了,变量j只在声明的时候做了一个初始化,后边没有任何引用(reference)。编译器认为这条语句没有任何作用,就给优化掉了。 另外在pure function,也就是叶子函数中,如果函数比较小,局部变量也有可能直接分配到寄存器里,这样能提高运行效率。嵌入式平台的编译器大都有这个优化功能。
nuanyangyang机器人#8 · 2015/5/23
【 在 xionger 的大作中提到: 】 : 书本上说的没有错,局部变量是在栈中分配,栈也是从高到底。 不,c语言甚至不提“地址”这个概念。变量对应的是“存储空间”,英文是object,定义是region of data storage。甚至没有说变量要存在内存里(可以是寄存器),所以不一定是栈,更提不上“从高到低”了。 : 但是不同的C++编译器实现的不一样,我用gcc 4.4.7你的代码是可以正确的,输出1。 : 我用vs2010中的c++编译器,i,j地址的差值不是1,而是3,我用cout<<*(p+3)就可以输出,编译器不一样可能结果不同,这只是在我的机器上是这样。 : ................... 来自「北邮人论坛手机版」
nuanyangyang机器人#9 · 2015/5/23
嗯,楼主观察到的这种现象可以用编译器的escape analysis来解释。c语言规定变量对应存储空间,但是如果编译器发现一个变量的指针从来未被获取,那么就不给它分配到内存里了,而是用寄存器、立即数等来表示。但是一旦取了它的地址,那么就“没办法作弊”了,只好老老实实给它分配个内存空间。然后碰巧编译器把这些变量按这种顺序分配在栈上(嗯,编译器完全可以不按这个顺序分配),所以楼主看到了这个现象。当然,修改优化等级、debug开关、换个编译器,都会造成现象不同。毕竟是“undefined behaviour”。 【 在 sxy0322 的大作中提到: 】 : 很简单。你没用到i,编译期自动优化,就当你没写过那个语句。 : 建议在gcc下不使用优化看效果。或者vs下debug模式运行后看效果,不排除不同版本也进行优化的可能。理论上你的想法是对的。 来自「北邮人论坛手机版」