精华内容
下载资源
问答
  • 通常所说的压栈什么意思呢?
  •  对于a++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来;而对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。 三、小试牛刀 ...

    一、问题

    c++代码:

    复制代码
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    int main(){
        int a=1;
        cout<<a++<<" "<<a<<endl;//12
        a=1;
        cout<<a<<" "<<a++<<endl;//21
        a=1;
        printf("%d %d\n",a,a++);//21
        a=1;
        printf("%d %d\n",a++,a);//12
    }
    复制代码

    java代码:

    复制代码
    public class Test{
        public static void main(String[] args){
            int a=1;
            System.out.println((a++)+" "+a);//1 2
            a=1;
            System.out.println(a+" "+(a++));//1 1
        
        }
      }
    复制代码

       对比两段代码,可知JAVA代码中比较有规律(从左到右),而C中的规律呢?(向下看)

    C代码:

    复制代码
    #include "stdafx.h"
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    int a=1;
    int afun(){
        printf("调用afun(){a++;}\n");
        return a++;
    }
    int bfun(){
        printf("调用bfun(){a;}\n");
        return a;
    }
    void main(){
        //printf("%d %d\n",a++,a);//12
        printf("%d %d\n",afun(),bfun());
    }
    复制代码

    运行结果:

      注意与之前直接打印所输出的结果不同(为什么啊???往下看):

    (1)直接打印 printf("%d %d\n",a++,a);//输出12

    (2)函数调用 printf("%d %d\n",afun(),bfun());//输出11

    二、原理(cout与printf原理一样)

    下面内容参考博文http://blog.csdn.net/kzzhr/article/details/8482657

                             http://www.zzzj.com/html/20090609/71613.html

          其实,在处理printf时,压栈顺序为从右往左,也就是说从右往左的计算(“计算”不等于“输出”)。

      a++和++a的压栈的区别:在计算时,遇到x++会记录此时的x的值作为最后的输出结果。遇到x和++x的时候不会将此时的计算结果作为最终的输出只会修改x的值,在最终输出的时候都输出x的值(所以++x和x的结果总是一样的)。

     

          为什么会是这个样子呢?参见某高手解释吧:

          对于a++的结果,是有ebp寻址函数栈空间来记录中间结果的,在最后给printf压栈的时候,再从栈中把中间结果取出来;而对于++a的结果,则直接压寄存器变量,寄存器经过了所有的自增操作。

    三、小试牛刀

    测试:

    a=1;   
    printf("%d %d %d %d %d %d\n",a++, ++a, a++, ++a, a++, ++a );  

    输出:6 7 4 7 2 7

    展开全文
  • java压栈和弹栈

    千次阅读 2020-01-14 10:57:57
    好好学习,天天向下 一、栈的存放 局部变量 ...堆中对象的引用(对象在堆内存中的 地址) ...栈的属性:每条线程都有一个独立的栈,在线程创建时创建 ...JVM对java栈只进行两种操作——>一帧为单位的压栈和弹栈

    好好学习,天天向下

    一、栈的存放

    • 局部变量
    • 堆中对象的引用(对象在堆内存中的 地址)
    • 全局变量存储在堆中
    • 局部变量存储在栈中
    • 栈的属性:每条线程都有一个独立的栈,在线程创建时创建

    二、栈的操作

    栈的存取顺序是先进后出,后进先出,就像是桶装羽毛球,先放进去的后拿出来

    public class storage {
        //先规定栈的最大容量
        Object[] objs;
        //获取当前栈容量
        int size;
    
        public void SQ(int MaxLen) {
            this.objs = new Object[MaxLen];
        }
        
        //进行压栈操作(就是在栈中存入内容)
        public void push(Object x) {
         //先给当前指针位置赋值,然后指针变大
            System.out.println("压栈操作,压入内容为" + (objs[size++] = x)); 
       }
    
        //弹栈操作
        public void popu() {
        //获取栈顶数据,然后弹出栈中,栈容量减少
            System.out.println("弹出栈顶内容:" + objs[size - 1]);
            size--;
        }
    
        //获取栈内所有数据
        public void getAllStack() {
            System.out.println("栈顶到栈底所有数据为");
            for (int i = size - 1; i >= 0; i--) {
                System.out.println(objs[i] + " ");
            }
        }
    }
    
    public class run {
        public static void main(String[] args) {
            storage storage = new storage();
            storage.SQ(20);
            storage.push(1);
            storage.push(2);
            storage.push(3);
            storage.push(4);
            storage.getAllStack();
            storage.popu();
            storage.popu();
            storage.getAllStack();
        }
    }
    

    三、栈和栈帧

    • java栈以帧为单位来保存线程的状态
    • JVM对java栈只进行两种操作——>一帧为单位的压栈和弹栈
    展开全文
  • 网上找的问题 现在贴出来应为比较常碰到 什么是堆和栈? 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据...

     网上找的问题 现在贴出来应为比较常碰到

     

     

    什么是堆和栈?
    一个由c/C++编译的程序占用的内存分为以下几个部分
    1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
    2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
    3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
    4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
    5、程序代码区—存放函数体的二进制代码。



    函数压栈是怎么回事?
    函数压栈的本质是参数传递
    这又跟汇编语言连系起来了.汇编语言的过程即proc可以理解成函数
    比如一个最简单的计算两数之和函数
    如果用汇编来写估计是这样的

    sub proc
    pop ax ;从stack取a 并放在AX寄存器中
    pop bx ;从stack取b 并放在BX寄存器中
    add ax,bx ; 计算a+b
    ret //返回
    sub endp

    显然要调用这个函数,你应当先把b值push进stack,然后再push a
    因为stack是先进后出的
    所以调用汇编像这样
    比如计算4+5
    push 5;
    push 4;
    call sub; //返回值在AX中
    在这个例子中先压5或先压4得到的结果没有变化
    但大多数程序,如果参数的顺序错误将是灾难性的


    因为不管什么高级语言最终都要编译成汇编语言,然后是机器语言
    同样下面这个C程序,计算a+b值,必然会编译成上面的汇编代码
    int sub(int a ,int b) {return a+b;}
    所以C在调用这个函数sub时,必须要压栈(即传入参数)但这些工作,在C语言里,并不需要你来完成.你只要写出
    sub(7,9);
    编译器在编译成汇编时就会自动完成相关的压栈工作.

    根据函数调用方式和参数压入顺序目前存在三种约定:

    stdcall
    cdecl
    fastcall
    这都相关压栈顺序和栈的清理工作约定
    他们的细节都不相同,但有一点是肯定的,参数比须从右向左压入栈中
    stdcall中 函数必须自已清理栈
    cdecall 由调用者清除堆栈 C的默认函数调用方式 所以这样C支持可变参数
    fastcall 是把函数参数列表的前三个参数放入寄存器eax,edx,ecx,其他参数压栈

    源代码:
    int function(int a, int b)
    {
    return a + b;
    }

    void main()
    {
    function(10, 20);
    }

    1.__cdecl

    _function
    push ebp
    mov ebp, esp
    mov eax, [ebp+8] ;参数1
    add eax, [ebp+C] ;加上参数2
    pop ebp
    retn
    _main
    push ebp
    mov ebp, esp
    push 14h ;参数 2入栈
    push 0Ah ;参数 1入栈
    call _function ;调用函数
    add esp, 8 ;修正栈
    xor eax, eax
    pop ebp
    retn

    2.__fastcall

    @function@8
    push ebp
    mov ebp, esp ;保存栈指针
    sub esp, 8 ;多了两个局部变量
    mov [ebp-8], edx ;保存参数 2
    mov [ebp-4], ecx ;保存参数 1
    mov eax, [ebp-4] ;参数 1
    add eax, [ebp-8] ;加上参数 2
    mov esp, ebp ;修正栈
    pop ebp
    retn
    _main
    push ebp
    mov ebp, esp
    mov edx, 14h ;参数 2给EDX
    mov ecx, 0Ah ;参数 1给ECX
    call @function@8 ;调用函数
    xor eax, eax
    pop ebp
    retn

    3.__stdcall

    _function@8
    push ebp
    mov ebp, esp
    mov eax, [ebp] ;参数 1
    add eax, [ebp+C] ;加上参数 2
    pop ebp
    retn 8 ;修复栈
    _main
    push ebp
    mov ebp, esp
    push 14h ;参数 2入栈
    push 0Ah ;参数 1入栈
    call _function@8 ;函数调用
    xor eax, eax
    pop ebp
    retn

    展开全文
  • C/C++函数调用的压栈模型

    千次阅读 2018-05-18 19:18:29
    函数调用的压栈模型对于我们学习C语言非常重要,最直观的体现在我们后面要学的函数的递归,函数的递归就充分利用的函数的压栈模型 当函数从入口函数main函数开始执行时,编译器会将我们操作系统的运行状态,main...

           函数调用的压栈模型对于我们学习C语言非常重要,最直观的体现在我们后面要学的函数的递归,函数的递归就充分利用的函数的压栈模型

            

            当函数从入口函数main函数开始执行时,编译器会将我们操作系统的运行状态,main函数的返回地址、main的参数、mian函数中的变量、进行依次压栈;当main函数开始调用fa()函数时,编译器此时会将main函数的运行状态进行压栈,再将fa()含糊的返回地址、fa函数的参数、fa定义变量依次压栈;当fa调用fb的时候,编译器此时会将fa函数的运行状态进行压栈,再将fb含糊的返回地址、fb函数的参数、fb定义变量依次压栈。

            

            当函数fb运行完成后,fb所有的压栈都会被编译器释放掉,编译器再从栈中接收到fa函数的运行状态后,衔接调用fb函数之前的操作,继续执行,同理,fa执行完后,编译器对mian函数的处理也相同。

            一个函数可以在栈上分配内存,也可以在堆上分配内存,更可以在全局区域分配内存,因此理解内存从哪里来,对于我们函数参数的传递,变量的调用异常重要。

            fb函数在栈上分配的内存,不能被fa和mian函数所调用,因为它会在fb函数执行完后被编译器释放掉;而 fb函数使用new或者malloc在堆上分配的内存或者在全局区分配的内存,只要不被程序员自己释放掉,是可以可以被fa和main函数所调用的。


    展开全文
  • 最近看到一些程序员的笔试题目,经常会考到printf函数的参数压栈问题,总体来讲就是参数从右向左依次压栈,再出栈,但是今天看到一个看似很简单的题目,却一直找不到头绪。题目如下: [cpp] view ...
  • printf() 函数压栈方式 转自网易博客 C语言,C++函数调用压栈方式取决与编译器。 但是一般编译器是右序压栈的。 下面介绍一下C 语言是如何右序压栈的: 如下函数: #include int main() { int a ...
  • 什么是压栈操作?指令:PUSH src ;src为16位操作数 功能:SP (SP)-2 (SP) PUSH [BX] PUSH DS
  • 在《c和指针》中已经说明了从右向左压栈的原因,这样可以保证生成汇编语言时这些参数相对于BP指向的栈位置的偏移量是固定的,因为程序员有时为函数传递的参数会或多或或少,如果从左向右压栈,则从BP指向的位置到...
  • 1.压栈和出栈:: 压栈也称进栈,例如一个正在执行程序被中断函数打断,需要从 A 函数跳到中断服务函数,此时为了保持A函数执行进度,需要进行保护现场(进栈),出栈对应就是恢复现场; 压栈和进栈遵循:先入后...
  • 具体的压栈指令,例子

    千次阅读 2015-11-23 21:42:07
    设(AX) = 1020H ,执行PUSH AX 前后对比:
  • <script type="text/javascript"> console.log('one'+i); //变量的声明提升 var i= 1;... //压栈 foo(i+1); //递归调用 console.log('three'+i); //出栈 } console.log('four'+i); &
  • 小甲鱼零基础入门学习python笔记

    万次阅读 多人点赞 2019-08-14 11:06:30
    应用范围:操作系统、WEB、3D动画、企业应用、云计算 大家可以学到什么:Python3的所有常用语法、面向对象编程思维、运用模块进行编程、游戏编程、计算机仿真 Python 是脚本语言 脚本语言(Scripting language)是...
  • 区块链数据压栈

    2018-06-13 11:32:59
  • 数组模拟压栈和弹栈

    2018-07-26 21:50:10
    #include &lt;iostream&gt; #define MAXSIZE 50 using namespace std; bool push(int *stack,int PushX,int &amp;top) {  if(top==MAXSIZE)  {  cout&lt;&lt;"......
  • 汇编 压栈出栈

    千次阅读 2016-03-20 20:54:47
    每一次发生函数的调用(主函数调用子函数)时,在被调用函数初始时,都会把当前函数(主函数)的EBP压栈,以便从子函数返回到主函数时可以获取EBP。 下面是按调用约定__stdcall 调用函数test(int p1,int p2)的...
  • 堆栈在内存中的压栈和弹栈工作原理 一.概述:  网上关于堆栈的文章很多,但多为不祥尽.趁清明假期整理验证下.VC编译,XP平台. 调用函数入栈过程分以下5步: 1.压参数(右向左)-->2.压调用完函数后的第一条汇编...
  • Java基础面试题

    千次阅读 2019-06-03 16:59:59
    hash是散列的意思,即把任意长度的输入,通过散列算法转换成固定长度的输出,该输出就是散列值 1.不同关键字经过散列算法变换后可能会得到同一个散列地址,这种的称为Hash碰撞 2.如果两个Hash值不同,(前提是同一个...
  • 汇编的压栈(PSHM)和出栈(POPM)

    千次阅读 2016-12-10 21:57:56
    此时压栈完成,继续push与此类似,push总是先压入高地址,再压低地址,而且必须是以字为单位,也就是必须2个字节 2个字节压入。   2: 然后执行pop bx出栈执行   出栈操作与压栈相反 ,先把 SS:...
  • 此处找到从m到n的路径,意思是此时栈中可以找到m到n的路径,即栈存储的都是n的祖先 (默认为非递归,递归的话一股脑全输出了没法操作) #mermaid-svg-jK6gpvtfH5r2gTqf .label{font-family:'trebuchet ms', verdana, ...
  • 栈是什么意思

    千次阅读 2019-09-16 19:28:45
    向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。 栈按照先进后出...
  • 堆栈是什么意思

    千次阅读 2017-04-29 23:09:50
    压栈的过程中,每有一个数据压入堆栈,就放在和前一个单元相连的后面一个单元中,堆栈指示器中的地址自动加1。读取这些数据时,按照堆栈指示器中的地址读取数据,堆栈指示器中的地址数自动减 1。这个过程叫做“弹...
  • 汇编

    千次阅读 2016-12-24 15:42:33
    表示同一个意思,即把eax寄存器的内容放入edx寄存器。这里需要注意的是AT&T格式的movl里的l表示指令的操作数都是32位,类似的还是有movb,movw,movq,分别表示8位,16位和64位的操作数。 X86汇编 文档 ...
  • 函数压栈

    2012-05-09 08:57:29
    有的压栈是按照从左到右进行压栈,有的压栈是按照从右到左进行压栈,有的不压栈、直接用寄存器代替,有的是需要被调用函数自身自己平衡堆栈。下面,我们就可以一个一个自己看看。首先,随便写一个函数, [cpp...
  • 答: 使用git stash -p进行交互式操作,y表示压栈,n表示不压栈 转载于:https://www.cnblogs.com/dakewei/p/11189407.html
  • ``` 递归的本质就是用压栈与出栈操作 ``` 这句话感觉很有道理啊
  • 1. ebp指向了本次函数调用开始时的栈顶指针,它也是本次函数调用时的“栈底”(这里的意思是,在一次函数调用中,ebp向下是函数的临时变量使用的空间)。在函数调用开始时,我们会使用 mov ebp,esp 把当前的esp保存...
  • 一、概念   对齐跟数据在内存中的位置有关。... 二、为什么要字节对齐    需要字节对齐的根本原因在于CPU访问数据的效率问题。假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取
  •  _stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数。  _cdecl是C...
  • public String alermStation() { // 1.查询数据库运行监控表的数据,返回唯一ElecCommonMsg ElecCommonMsg elecCommonMsg = elecCommonMsgService.findElecCommonMsg(); // 2.... ValueUtils.putValueStack...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,071
精华内容 5,628
关键字:

压栈是什么意思