C语言中:栈的伸展方向到底是什么啊? 我今天被嘲笑了。。

BAO BAO 2018-01-31 06:39:28
首先看到网上很多网页 都说:
栈就是从高地址向低地址增长 先声明的先入栈
栈是先入后出的,一般是由高地址向低地址生长。
生长方向:
对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;
对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

栈的伸展方向是由高地址向低地址扩展的

以上都是网上看到的 然后我用c运行
#include<stdio.h>
int main()
{
int a,b;
printf("%d %d",&a,&b);
}


发现只有在debug模式下运行 才和网上说的相符合
debug运行结果:
2686756 2686752

release 模式运行结果就成了:2686752 2686756
这咋么又成了地址往高地址增长了???

我不太懂 ,请大家给我仔细讲解下 是我误解了吗?谢谢了
...全文
951 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
断水客 2020-03-24
  • 打赏
  • 举报
回复
栈的伸展方向和处理器有关。早一些的51系列是向高地址生长的,称为正向生长。8086系列是向低地址生长的,称为逆向生长。
稻云麦花 2020-02-18
  • 打赏
  • 举报
回复
你没有控制变量,输出的地址谁大谁小受栈生长方向和局部变量分配顺序两个英雄。
栈的生长方向是取决于处理器所采用的指令架构的。
而你的使用的测试代码的输出不但涉及到栈的生长方向;还涉及到编译器给局部变量分配空间的顺序问题,而对于这个问题(实际上标准是没有规定的,因为没必要,因为编程者想要的只是一个抽象的可以存储东西的变量,而不关心a和b在内存中的绝对位置或者相对位置,如果你需要固定相对位置的话,可以通过struct或者数组解决),既然没有规定,那么编译器的实现者就可以自由发挥了。
另外,从编译原理的角度来看,debug和release两种模式下的编译器是两个编译器,因为它们生成的目标代码不一样(虽然目标代码所属的种类一样)。当然,debug和release出现这样的差异的确比较神奇(不过可能debug和release是两个小组的人员分别实现不同的部分,然后共有部分又是一批人实现的),对于语言标准没定,而且又不怎么要紧的实现细节出现不一致也不是什么难以理解的事)
当然,虽然局部变量的分配顺序没定,但是函数调用时参数传递压栈的顺序是有规定的(如果需要详细了解细节,应当查看调用规范。__cdecl,__fastcall,__stdcall,__pascal)。
当然,你在debug和release模式下的运行不一致,说明应该是两种模式下编译器的解释不一致,具体可以生成汇编代码查看。
断水客 2020-02-10
  • 打赏
  • 举报
回复
栈的伸展方向是不确定的,这一点在<UNP>中有谈到,栈的伸展方向并没有统一的规定,只区分地址的大小端。可能是自顶而下,也可能是自下而上。
schlafenhamster 2018-02-05
  • 打赏
  • 举报
回复
8086的堆栈指针,压栈时,SP减去2,是按照地址递减的方向生成堆栈; 8031的堆栈指针,压栈时,SP加上1,是按照地址递增的方向生成堆栈。 arm 甚至可以改变。
赵4老师 2018-02-05
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!) VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
horris 2018-02-04
  • 打赏
  • 举报
回复
特别是2#3#答乃所问
horris 2018-02-04
  • 打赏
  • 举报
回复
1-9#说的对,10#12#讲的不对
schlafenhamster 2018-02-02
  • 打赏
  • 举报
回复
和所使用的cpu硬件结构有关,如同 大小 端 问题。
cattpon 2018-02-02
  • 打赏
  • 举报
回复
由高地址向低地址生长
meetofly 2018-02-02
  • 打赏
  • 举报
回复
你可以用struct包起来再看,struct里按顺序来的
ba_wang_mao 2018-02-01
  • 打赏
  • 举报
回复
栈的伸展方向说白了,就是入栈时堆栈指针是从高地址向低地址递减还是堆栈指针是从低地址向高地址递增。 具体中哪种,和所使用的单片机硬件结构有关。
烟袅许伊 2018-02-01
  • 打赏
  • 举报
回复
这个楼主看一下反汇编,变量声明通常是顺序生命的,也就是IP(Instruction Pointer)增长的方向,这样便于人的理解,而楼主所说的栈,是程序调用栈,是在函数调用之前,即汇编call之前的函数参数入栈过程,即push,这个栈的顺序是逆IP方向的,这样的设计好处是充分利用地址空间。楼上所说的调用约定(Calling Convention),跟你说的我觉得是不一样的。楼主可以看一下函数调用,稍微学一下汇编,就懂了。
destory27 2018-02-01
  • 打赏
  • 举报
回复
该语言标准并没有规定,可以向上可以向下,,但操作系统规定是向下的
CT8100 2018-02-01
  • 打赏
  • 举报
回复
四种物件的生存方式(in stack、int heap、global、local static)
ckc 2018-02-01
  • 打赏
  • 举报
回复
并没有规定栈一定要向哪个方向伸展,这个跟具体的cpu架构有关,有向上的有向下的 int a,b这个也没有规定哪个先入栈哪个后入栈,不同的编译器不同的情况有不同完全是可能的 最后,这个问题其实并不重要,绝大多数情况下你并不应该关心它向上增长还是向下增长 记得先进后出就好了
super_admi 2018-01-31
  • 打赏
  • 举报
回复
其实我是看到“嘲笑”两个字进来的。 1.会嘲笑别人的人,一般都是半桶水,区别只是大半桶还是小半桶而已; 2.想学东西,或者想做事情,就不要怕嘲笑,脸皮一定要厚实才行。
热血打工人 2018-01-31
  • 打赏
  • 举报
回复
栈确实是从高到低增长 你写的代码需要注意编译器的调用方式: cdecl、stdcall、fastcall函数调用 详细文档http://blog.csdn.net/fly2k5/article/details/544112
zwfgdlc 2018-01-31
  • 打赏
  • 举报
回复
从C语言层面上不好解释,在汇编层面又是基础知识. 局部变量申请一般都是sub esp 8这类的指令,也可以说是由高地址向低地址生长,建议看下汇编相关的知识,不是很复杂的.
paschen 2018-01-31
  • 打赏
  • 举报
回复
int a,b; 标准并没有要求编译器非得把a放在b的前面,你定义a b变量也不是一个压栈的过程,和栈生长方向没什么关系
加载更多回复(1)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧