zoukankan      html  css  js  c++  java
  • 变量的内存分配情况

    接触过编程的人都知道,高级语言都能通过变量名访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序
    又是如何使用这些变量的呢?
    首先,来了解一下C语言的变量是如何在内存分布的。C语言有全局变量(Global)、本地变量(Local)、静态变量
    (Static)和寄存器变量(Register)。每种变量都有不同的分配方式。先来看下面这段代码:

    编译后的执行结果是:

           

    输出的结果就是变量的内存地址。其中v1、v2、v3是本地变量,g1、g2、g3是全局变量,s1、s2、s3是静态变量。你
    可以看到这些变量在内存中是连续分布的,但是本地变量和全局变量分配的内存地址差了十万八千里,而全局变量和静态
    变量分配的内存是连续的。这是因为本地变量和全局/静态变量是分配在不同类型的内存区域中的结果。对于一个进程的
    内存空间而言,可以在逻辑上分成3个部分:代码区、静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈
    (stack)”和“堆(heap)”是两种不同的动态数据区。栈是一种线性节构,堆是一种链式节构。进程的每个线程都有私有
    的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰的。
    一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据
    区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量,如下图所示。

    堆栈是一个先进后出的数据结构,栈顶地址总是小于等于栈的基地址。我们可以先了解一下函数调用的过程,以便对
    堆栈在程序中的作用有更深入的了解。不同的语言有不同的函数调用规定,这些因素有参数的压入规则和堆栈的平衡。
    Windows API的调用规则和ANSI C的函数调用规则是不一样的,前者由被调函数调整堆栈,后者由调用者调整堆栈。两者
    通过“_stdcall”和“_cdecl”前缀区分。先看下面这段代码:

    编译后的执行结果是:

    下面详细解释函数调用的过程中堆栈的分布:
    在堆栈中分布变量是从高地址向低地址分布,EBP指向栈底指针,ESP是指向栈顶的指针,根据__stdcall调用约定,参
    数从右向左入栈,所以首先,3个参数以从右到左的次序压入堆栈,先压“param3”,再压“param2”,最后压入“param1”。
    栈内分布如下图所示。

    然后函数的返回地址入栈,栈内分布如下图所示。

    通过跳转指令进入函数。函数地址入栈后,EBP入栈,然后把当前的ESP的值给EBP,汇编下指令为:

    此时栈底指针和栈顶指针指向同一位置,栈内分布为如下图所示。

    然后是int var1=param1;int var2=param2;int var3=param3;也就是变量var1,var2,var3的初始化(从左向右的顺序入
    栈),按声明顺序依次存储到EBP-4,EBP-8,EBP-12位置,栈内分布如下图所示。

    Windows下的动态数据除了可存放在栈中,还可以存放在堆中。了解C++的朋友都知道,C++可以使用new关键字来
    动态分配内存。来看下面的C++代码:

    程序执行结果为:

    可以发现用new关键字分配的内存既不在栈中,也不在静态数据区

  • 相关阅读:
    mybatis批量插入、批量更新和批量删除
    MySQL本地密码过期处理及永不过期设置
    Intellij IDEA安装与使用,完整详细。
    深入浅出mybatis之useGeneratedKeys参数用法
    springmvc_learn
    Mac下,MySQL数据库中文乱码的解决方法
    springmvc整合mybatis实现商品列表查询
    sql server 数据库导出表里所有数据成insert 语句
    推荐几个bootstrap 后端UI框架
    50个极好的bootstrap框架
  • 原文地址:https://www.cnblogs.com/yihujiu/p/6377204.html
Copyright © 2011-2022 走看看