精华内容
下载资源
问答
  • RAM中局部变量在栈中分配

    千次阅读 2016-09-28 18:42:15
    无OS时,RAM的使用可以分为数据、和堆区域;有OS时,将RAM分成若干个段,每个任务分配一个段,用于各自的数据、和堆区域。... 编译器局部变量分配空间时通常有两种做法:使用寄存器和使用。寄存

           无OS时,RAM的使用可以分为数据、栈和堆区域;有OS时,将RAM分成若干个段,每个任务分配一个段,用于各自的数据、栈和堆区域。


           局部变量(Local Variable)是指作用域和生命周期都局限在所在函数或过程范围内的变量,它是相对于全局变量(Global variable)而言的。

           编译器在为局部变量分配空间时通常有两种做法:使用寄存器和使用栈。寄存器的访问速度快,但数量和空间有限,所以像字符串或数组不适合分配在寄存器中。编译器通常只会把频繁使用的临时变量分配在寄存器中,比如for循环中的循环变量。

           栈上的变量会随着函数的调用和返回而自动分配和释放,所以栈有时也称为自动内存。编译器在编译时,会计算当前的代码块中所声明的所有局部变量所需要的空间,并将其按照内存对齐要求来分配3,一般为4字节对齐。


           X86 CPU中定义了栈指针ESP(栈顶)寄存器,和栈基址指针EBP(栈底)寄存器,使用EBP寄存器,函数可以把自己将要使用的栈空间的基准地址记录下来,然后使用这个基地址来引用局部变量和参数。在同一函数内,EBP寄存器的值是保持不变的,这样函数的局部变量就有了一个固定的参照物。

           通常,一个函数在入口处将当时的EBP值压入堆栈1,然后把ESP值(栈顶)赋值给EBP2,这样EBP中的地址就是进入本函数时的栈顶地址。

     

           每个函数在栈中所使用的区域称为一个栈帧(stack frame),每发生一次函数调用,便产生一个新的栈帧,当一个函数返回时,这个函数所对应的栈帧被清除。

    展开全文
  • 根据“Java中的变量与数据类型”中的介绍,“变量在内存中分配的保留区域的名称。换句话说,它是一个内存位置的名称”,也就是说我们通过这个变量名字就可以找到一个指向这个变量所引用的数据的内存指针,根据变量...

    Java中的变量根据不同的标准可以分为两类,以其引用的数据类型的不同来划分可分为“原始数据类型变量和引用数据类型变量”,以其作用范围的不同来区分可分为“局部变量,实例变量和静态变量”。

    根据“Java中的变量与数据类型”中的介绍,“变量是在内存中分配的保留区域的名称。换句话说,它是一个内存位置的名称”,也就是说我们通过这个变量名字就可以找到一个指向这个变量所引用的数据的内存指针,根据变量的类型我们可以知道这个指针之后的几个字节里存储了这个变量所引用的数据。

    所以,了解变量在方法区、栈内存、堆内存中的分配要了解两部分内容,一个是“变量在内存中的分配”,另一个是“变量所引用的数据在内存中的分配”。以下简称为“变量分配”与“数据分配”。

    原始数据类型变量

    原始数据类型变量的“变量分配”与“数据分配”是在一起的(都在方法区或栈内存或堆内存)

    引用数据类型变量

    引用数据类型变量的“变量分配”与“数据分配”不一定是在一起的

    示例代码

    class Fruit {
        static int x = 10;
        static BigWaterMelon bigWaterMelon_1 = new BigWaterMelon(x);
    
        int y = 20;
        BigWaterMelon bigWaterMelon_2 = new BigWaterMelon(y);
    
        public static void main(String[] args) {
            final Fruit fruit = new Fruit();
    
            int z = 30;
            BigWaterMelon bigWaterMelon_3 = new BigWaterMelon(z);
    
            new Thread() {
                @Override
                public void run() {
                    int k = 100;
                    setWeight(k);
                }
    
                void setWeight(int waterMelonWeight) {
                    fruit.bigWaterMelon_2.weight = waterMelonWeight;
                }
            }.start();
        }
    }
    
    class BigWaterMelon {
        public BigWaterMelon(int weight) {
            this.weight = weight;
        }
    
        public int weight;
    }

    内存分配图

    同一种颜色代表变量和对象的引用关系

    由于方法区和堆内存的数据都是线程间共享的,所以线程Main Thread,New Thread和Another Thread都可以访问方法区中的静态变量以及访问这个变量所引用的对象的实例变量。

    栈内存中每个线程都有自己的虚拟机栈,每一个栈帧之间的数据就是线程独有的了,也就是说线程New Thread中setWeight方法是不能访问线程Main Thread中的局部变量bigWaterMelon_3,但是我们发现setWeight却访问了同为Main Thread局部变量的“fruit”,这是为什么呢?因为“fruit”被声明为final了。

    当“fruit”被声明为final后,“fruit”会作为New Thread的构造函数的一个参数传入New Thread,也就是堆内存中Fruit$1对象中的实例变量val$fruit会引用“fruit”引用的对象,从而New Thread可以访问到Main Thread的局部变量“fruit”。


    以下内容更新于 2021年04月17日 05:38:09

    看到很多同学提出疑问,特此更正下之前的理解错误:

    内部类(new Thread)中可以访问局部变量(mainThreadLocalPrice、fruit、sweet)是因为内部类会自动生成成员变量(val$mainThreadLocalPrice、val$fruit、val$sweet)来引用局部变量的引用;

    在 java8 中可以不显示的将局部变量声明为 final(相关错误: 从内部类引用的本地变量必须是最终变量或实际上的最终变量)

    测试结果

    Class   : miao.app.memoryarea.Fruit [3982074834] == miao.app.memoryarea.Fruit@66d3c617 [3982077873]
    Field[0]: constantPrice [3982078152] == 50 [3982089650]
    Field[1]: constantName [3982078161] == 水果 [3982074851]
    Field[2]: staticPrice [3982078170] == 100 [3982090278]
    Field[3]: thin [3982078179] == miao.app.memoryarea.BigWaterMelon@63947c6b [3982077862]
    Field[4]: instancePrice [3982078188] == 200 [3982091469]
    Field[5]: juicy [3982078197] == miao.app.memoryarea.BigWaterMelon@2b193f2d [3982077876]
    	
    Class   : miao.app.memoryarea.Fruit$1 [3982094116] == Thread[Thread-0,5,main] [3982094131]
    Field[0]: val$mainThreadLocalPrice [3982676303] == 300 [3982677048]
    Field[1]: val$fruit [3982676312] == miao.app.memoryarea.Fruit@66d3c617 [3982077873]
    Field[2]: val$sweet [3982676321] == miao.app.memoryarea.BigWaterMelon@b676557 [3982092217]

    测试代码

    /**
     * Created by 鲜榨(177421) - 86336991@qq.com on 2021/4/13.
     */
    
    public class Fruit {
        final static int constantPrice = 50;
        final static String constantName = "水果";
    
        static int staticPrice = 100;
        static BigWaterMelon thin = new BigWaterMelon("皮薄", staticPrice);
    
        int instancePrice = 200;
        BigWaterMelon juicy = new BigWaterMelon("多汁", instancePrice);
    
        public static void main(String[] args) {
            Fruit fruit = new Fruit();
            //打印对象字段
            printFields(fruit);
    
            int mainThreadLocalPrice = 300;
            BigWaterMelon sweet = new BigWaterMelon("超甜", mainThreadLocalPrice);
    
            new Thread() {
                @Override
                public void run() {
                    int subThreadLocalPrice = mainThreadLocalPrice;
                    setPrice(subThreadLocalPrice);
                }
    
                void setPrice(int price) {
                    fruit.juicy.setPrice(price);
                    fruit.thin.setPrice(price);
                    sweet.setPrice(price);
                    //打印对象字段
                    printFields(this);
                }
            }.start();
        }
    }
    
    /**
     * 大西瓜
     */
    class BigWaterMelon {
        //品种
        private String name;
        //价格
        public int price;
    
        public BigWaterMelon(String name, int price) {
            this.name = name;
            this.price = price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    }
    

    内存分配图v2

    展开全文
  • C语言局部变量在内存栈中的顺序

    千次阅读 2017-08-23 20:44:10
    规则1:内存由低到高优先分配给占位8字节、4字节、2字节、1字节的数据类型 数据类型占位说明: 8字节:double、longlong int 4字节:int、float、long int、unsigned int 2字节:short 、unsigned short

    首先总结规则,详细分析见下面:
    规则1:内存由低到高优先分配给占位8字节、4字节、2字节、1字节的数据类型
    数据类型占位说明:
    8字节:double、longlong int
    4字节:int、float、long int、unsigned int
    2字节:short 、unsigned short
    1字节:char 、unsigned char
    例如,分别定义下列变量,内存地址中由低到高分别为:
    double < int < short < char
    规则2:同总占位的类型按定义变量的先后顺序内存地址会增加
    规则3:在规则2前提下,定义数组不会和同总数据类型混占内存
    下面看示例程序:

    示例程序1#include <stdio.h>
    
    int main(int argc, const char *argv[])
    {
        char char_a;
        short short_a;
        int int_a;
        float float_a;
        double double_a;
        unsigned int uint_a;
        long int lint_a;
        long long int dlint_a;
    
        printf("  &char_a : %p\n",&char_a);
        printf(" &short_a : %p\n",&short_a);
        printf("   &int_a : %p\n",&int_a);
        printf(" &float_a : %p\n",&float_a);
        printf("&double_a : %p\n",&double_a);
        printf(" &unsigned_int_a : %p\n",&uint_a);
        printf("     &long_int_a : %p\n",&lint_a);
        printf("&long_long_int_a : %p\n",&dlint_a);
        return 0;
    }
    
    测试结果1:
    *不同机器显示的内存地址会略有不同*
      &char_a : 0xbfa844af
     &short_a : 0xbfa844ac
       &int_a : 0xbfa8449c
     &float_a : 0xbfa844a0
    &double_a : 0xbfa84488
     &unsigned_int_a : 0xbfa844a4
         &long_int_a : 0xbfa844a8
    &long_long_int_a : 0xbfa84490

    **分析:有结果可知变量下内存中的分布为(从低地址到高地址,()中为它们所占字节):
    double(8)、long long int(8)、int(4) 、float(4)、unsigned int(4)、long int(4)、short(2)、char(1)
    这里可以佐证规则1.**

    示例程序2#include <stdio.h>
    
    int main(int argc, const char *argv[])
    {
        char char_a;
        short short_a;
        int int_a;
        float float_a;
        double double_a;
        unsigned int uint_a;
        long int lint_a;
        long long int dlint_a;
        char char_b;
        short short_b;
        int int_b;
        float float_b;
        double double_b;
        unsigned int uint_b;
        long int lint_b;
        long long int dlint_b;
    
        printf("  &char_a : %p\n",&char_a);
        printf("  &char_b : %p\n",&char_b);
        printf(" &short_a : %p\n",&short_a);
        printf(" &short_b : %p\n",&short_b);
        printf("   &int_a : %p\n",&int_a);
        printf("   &int_b : %p\n",&int_b);
        printf(" &float_a : %p\n",&float_a);
        printf(" &float_b : %p\n",&float_b);
        printf("&double_a : %p\n",&double_a);
        printf("&double_b : %p\n",&double_b);
        printf(" &unsigned_int_a : %p\n",&uint_a);
        printf(" &unsigned_int_b : %p\n",&uint_b);
        printf("     &long_int_a : %p\n",&lint_a);
        printf("     &long_int_b : %p\n",&lint_b);
        printf("&long_long_int_a : %p\n",&dlint_a);
        printf("&long_long_int_b : %p\n",&dlint_b);
    
        return 0;
    }
    
    测试结果2:
    *不同机器显示的内存地址会略有不同*
      &char_a : 0xbfde982e
      &char_b : 0xbfde982f
     &short_a : 0xbfde982a
     &short_b : 0xbfde982c
       &int_a : 0xbfde9808
       &int_b : 0xbfde9818
     &float_a : 0xbfde980c
     &float_b : 0xbfde981c
    &double_a : 0xbfde97e8
    &double_b : 0xbfde97f8
     &unsigned_int_a : 0xbfde9810
     &unsigned_int_b : 0xbfde9820
         &long_int_a : 0xbfde9814
         &long_int_b : 0xbfde9824
    &long_long_int_a : 0xbfde97f0
    &long_long_int_b : 0xbfde9800

    分析:这里由int的两个变量a和b之间夹了float、unsigned int等变量,可以佐证规则2

    测试案例3#include <stdio.h>
    
    int main(int argc, const char *argv[])
    {
        char char_b[4];
        int int_b[4]; 
        char char_a;
        short short_a;
        int int_a;
    
        printf("  &char_a : %p\n",&char_a);
        printf(" &short_a : %p\n",&short_a);
        printf("   &int_a : %p\n",&int_a);
        printf("   &int_b : %p\n",int_b);
        printf("  &char_b : %p\n",char_b);
    
        return 0;
    }
    测试结果3*不同机器显示的内存地址会略有不同*
      &char_a : 0xbf8fdcc7
     &short_a : 0xbf8fdcc4
       &int_a : 0xbf8fdcc0
       &int_b : 0xbf8fdcb0
      &char_b : 0xbf8fdcc8
    
    测试案例4#include <stdio.h>
    
    int main(int argc, const char *argv[])
    {
        char char_a;
        short short_a;
        int int_a;
        int int_b[4]; 
        char char_b[4];
    
        printf("  &char_a : %p\n",&char_a);
        printf(" &short_a : %p\n",&short_a);
        printf("   &int_a : %p\n",&int_a);
        printf("   &int_b : %p\n",int_b);
        printf("  &char_b : %p\n",char_b);
    
        return 0;
    }
    
    测试结果4*不同机器显示的内存地址会略有不同*
      &char_a : 0xbfebf947
     &short_a : 0xbfebf944
       &int_a : 0xbfebf940
       &int_b : 0xbfebf930
      &char_b : 0xbfebf948
    

    **分析:案例3和4可以说明数组类型会在规则1的前提下,满足规则3.
    对于char类型变量,数组变量会存到高地址
    对于int类型变量,数组变量会存到低地址
    跟数组定义在前后没有关系**

    测试案例5#include <stdio.h>
    
    int main(int argc, const char *argv[])
    {
        double b[4];
        double a;
        printf("  &double_a : %p\n",&a);
        printf("  &double_b : %p\n",b);
    
        return 0;
    }
    
    测试结果:
    *不同机器显示的内存地址会略有不同*
     &double_a : 0xbfa3b688
     &double_b : 0xbfa3b668
    
    测试案例6#include <stdio.h>
    
    int main(int argc, const char *argv[])
    { 
    double a;
        double b[4];
        printf("  &double_a : %p\n",&a);
        printf("  &double_b : %p\n",b);
    
        return 0;
    }
    
    测试结果:
    *不同机器显示的内存地址会略有不同*
     &double_a : 0xbfd3bda8
     &double_b : 0xbfd3bd88

    **分析:由案例5和6可知、
    对于double类型变量,数组变量会存到低地址内存上,非数组变量会先对存到较高内存上,而与它们定义的先后没有关系

    总结分析:由上面的结果(1和2的测试)也可以看到,在占位不同的数据类型相邻的内存会自动对齐占位较高的内存。对齐方式是在高位占有自己数据大小的空间.**

    在数组方面还有short、unsigned int等没有测试,测试方法和案例5、6的方法一样,感兴趣的读者自行验证……

    因本人时间和水平有限,文中如有错讹、不当之处,敬请大神斧正。

    展开全文
  • 形式参数是局部变量局部变量的数据存在于栈内存中栈内存中局部变量随着方法的消失而消失。 成员变量存储堆中的对象里面,由垃圾回收器负责回收。 如以下代码:class BirthDate { private int day; ...

    对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。 如以下代码:

    class BirthDate {
        private int day;
        private int month;
        private int year;
    
        public BirthDate(int d, int m, int y) {
            day = d;
            month = m;
            year = y;
        }
        // 省略get,set方法………
    }
    
    public class Test {
        public static void main(String args[]) {
            int date = 9;
            Test test = new Test();
            test.change(date);
            BirthDate d1 = new BirthDate(7, 7, 1970);
        }
    
        public void change(int i) {
            i = 1234;
        }
    }

    对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,day,month,year为成员变量。下面分析一下代码执行时候的变化:

    1.main方法开始执行:int date = 9; date局部变量,基础类型,引用和值都存在栈中。

    2.Test test = new Test();test为对象引用,存在栈中,对象(new Test())存在堆中。

    3.test.change(date); i为局部变量,引用和值存在栈中。当方法change执行完成后,i就会从栈中消失。

    4.BirthDate d1= new BirthDate(7,7,1970); d1为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中d,m,y为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。day,month,year为成员变量,它们存储在堆中(new BirthDate()里面)。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。

    5.main方法执行完之后,date变量,test,d1引用将从栈中消失,new Test(), new BirthDate()将等待垃圾回收。
    这里写图片描述

    展开全文
  • 形式参数是局部变量局部变量的数据存在于栈内存中栈内存中局部变量随着方法的消失而消失。 成员变量存储堆中的对象里面,由垃圾回收器负责回收。 如以下代码: class BirthDate { private int day; ...
  • 对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量局部变量的数据存在于栈内存...
  • Java的变量根据不同的标准可以分为两类,以其引用的数据类型的不同来划分可分为“原始数据类型变量和引用数据类型变量”,以其作用范围的不同来区分可分为“局部变量,实例变量和静态变量”。 根据“...
  • 局部变量分配的内存在里:大小与编译器有关。默认情况下,visual studio 2010 的大小为1M。 全局变量存放静态存储区:对于全局变量来说,与编译器有关,默认情况下, VS2010可容纳的全局变量数组大小是2G...
  • 全局变量,静态局部变量局部变量空间的堆分配和栈分配 https://www.nowcoder.com/profile/217415501/test/22063497/14928#summary https://blog.csdn.net/xuehongnizhao/article/details/51074668 ...
  • 局部变量内存分配可能在栈上也可能堆上 堆和的简单说明: 1.(操作系统):由操作系统自动分配释放 2.堆(操作系统): 一般由程序员分配释放,例如c/c++golang,java,python有自动的垃圾回收机制 ...
  • #include void _stdcall func(int param1,int param2,int param3) { int var1 = param1; ...int var2 = param2;...printf("函数参数入栈顺序(栈在内存中向上伸长):从右到坐\n"); printf("¶m1:0x%08x\n",&par
  • C++ 在栈分配内存

    千次阅读 2020-01-02 09:44:09
    malloc与alloc的区别 malloc()与 alloc() ...执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配...
  • 来源: java数据的5种存储位置(堆与) ...Java面向对象——成员变量和局部变量(成员变量和局部变量的初始化和内存运行机制&变量的使用规则) http://www.cnblogs.com/newveg/p/6591435.htm
  • 【应用C】局部变量空间分配

    千次阅读 2019-01-14 22:15:03
    有时候,C语言的循环,如果编程时对边界判断错误,就会带来意想不到的结果,小白本文提及一个有趣的C语言问题,此问题并不是小白原创,而是一本编程书的考核内容,小白将其分享到此。 C语言有趣的...
  • 全局变量和局部变量在内存中的区别

    万次阅读 多人点赞 2016-06-29 22:27:14
    局部变量保存在栈中,只有所在函数被调用时才动态地为变量分配存储单元。 该题目考查的知识点是变量的存储类型及性质。C语言经过编译之后将内存分为以下几个区域: (1)(stack):由编译器...
  • c语言内存分配局部变量内存分配

    千次阅读 2013-04-26 14:44:42
    局部变量保存在栈中(保存地址由高地址到低地址)。 先定义先分配内存。     由此可见局部变量分配空间的顺序和变量的声明顺序直接相关,同时按照内存地址由高到低的顺序进行空间分配. 先定义,先分配,...
  • 全集变量、局部变量、静态全局变量、静态局部变量在内存中如何存储,有什么区别,和堆的区别,这都是C/C++的基础问题。各种招聘笔试面试中,经常都能够遇到与之相关的问题。前些日子我看了一些与之相关的文章,...
  • 看书时发现了这几个概念有些混乱,和同学们讨论也觉得这个地方没搞懂,包括网上的一些对于这方面的介绍,让自己更糊涂了。花了几天时间,稍微弄懂了些。 之所以有些混乱,我觉得是基本概念没有搞清楚,我查阅了...
  • 全局变量和局部变量在内存里的区别?堆和 转:一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等...
  • 局部变量什么时候分配内存

    千次阅读 2013-02-27 16:03:34
    就一直以为局部变量内存是由编译器分配,也没多想怎么分配。 今天被别人问到 “程序执行的过程编译器怎么还能参与内存分配” 一下就傻眼了,网上查了下,这句话的意思应该是  “ 编译器编译的过程
  • 学习了C++这么久,内存问题感觉一直...我们知道当一个函数进行调用时,函数的形参、以及函数的局部变量都会在栈中分配内存,而又可分为两种,一种是底不变,栈顶不断的动态变化;另一种是栈顶不变,动态变
  • 单片机全局变量 局部变量 堆与

    千次阅读 2017-01-06 12:50:11
    局部变量,全局变量
  • 全局、静态、new产生的变量都,动态分配的变量中分配局部变量在栈里面分配。函数声明的变量在栈中,用了new标识符,全局变量和static变量全局区。程序为变量分配动态内存程序结束为...
  • 在栈中分配内存的方法 alloca 例子

    千次阅读 2014-09-18 16:58:01
    声明一个局部变量,一定是在栈分配,但有无其方法 当然有,那就是 alloca 下面代码显示转化变长参数,alloca 的用法 #include int main(int argc, char ** argv) { char **argv2; int i,n; n=0; ...
  • 局部变量保存在栈中,只有所在函数被调用时才动态地为变量分配存储单元。引申: C语言经过编译之后将内存分为以下五个区域 1.:由编译器进行管理,自动分配和释放,存放函数调用过程的各种参数,局部变量,...
  • 概念首先得明白局部变量,静态局部变量,全局变量,静态全局变量这几个概念,以下面程序举例://main.cpp int a = 0; //全局变量 static int b=0;//静态全局变量 main() { int c; //局部变量 static int d;//静态...
  • 成员变量内存里,局部变量在栈内存里。(基础类型)我有疑惑:既然成员变量存在于对象,对象存在于堆,所以成员变量存在于堆。那么按照这样的推理,局部变量存在于方法,而方法存在于对象,对象存在于...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 153,039
精华内容 61,215
关键字:

局部变量是在栈中分配内存吗