数组在内存中如何分配:区分栈堆与静态区

数组在内存中如何分配,主要由数组的声明位置、存储类型、是否动态开辟决定,局部非静态数组默认分配在栈内存,全局数组、static修饰的静态数组分配在静态存储区,new、malloc创建的数组分配在堆内存,栈数组长度必须是编译期常量,栈空间容量通常较小,Windows环境下栈大小一般为1MB左右,超出会触发栈溢出,堆内存容量更大,由程序员手动管理释放,静态区数组在程序启动时分配、程序结束才释放,该分配规则适用于C、C++语言,Java、Python等托管语言数组底层机制不一样,不能直接套用这套判断方式。

数组在内存中如何分配:栈内存数组

栈内存上的数组随函数调用创建,函数执行结束自动回收内存,不需要手动释放。数组名代表数组首元素的地址,数组内部元素是连续紧凑排布,地址由低到高依次存放每个成员。你定义数组时方括号内的长度必须是编译阶段就能确定的常量,C99变长数组是特例,它语法允许变量指定长度,但依然存放在栈上,变长数组的兼容性在部分编译器上支持有限。

栈内存分配速度快。

数组在内存中如何分配:堆内存数组

堆内存数组使用malloc或者new关键字申请,申请成功后返回首地址,需要用指针接收,数组元素同样连续存放,但内存生命周期不受函数作用域约束。你用完之后必须调用free或者delete释放对应的内存,不及时释放会形成内存泄漏,程序长时间运行后可用堆空间持续变少。堆分配的开销高于栈,系统需要查找空闲内存块,分配耗时会明显更长。

数组在内存中如何分配:静态存储区数组

写在函数外部的全局数组、函数内部加static修饰的数组,都会放在静态存储区。这部分内存和栈、堆相互独立,初始化只执行一次,就算函数多次调用,数组只分配一次内存,里面的值会保留上一次修改后的结果。静态存储区分成初始化静态区和未初始化静态区,未显式初始化的数组元素会默认填充0。

不同内存区域数组对比

内存区域分配方式释放时机长度限制
栈自动分配函数退出自动释放偏小,常量长度为主
堆手动申请代码手动释放容量大,支持变量长度
静态区程序加载分配程序退出释放受程序全局内存限制

数组在内存里的排布规则统一,无论分配在哪一块区域,元素地址连续,数组名指向首元素地址,多维数组在内存中也会展开成一维连续序列,C、C++采用行优先展开,先存完一行全部元素再继续下一行。多维数组只是语法层面的包装,底层不存在多行分段存储。

数组名本身不是指针,在多数表达式场景下会隐式转为首元素指针,存在两个例外:sizeof(数组名)得到整个数组占用字节数,&数组名取到整个数组的地址,地址数值和首元素地址一致,但类型不相同,做加减运算时步长有区别。

变长数组不能作为全局变量,C标准不允许全局变长数组。

托管语言的数组由虚拟机自动托管内存,Java数组全部在堆上分配,基础类型数组存放数值,引用类型数组存放对象引用,Python列表不是原生数组,底层是动态扩容结构,元素地址并不连续,不能直接沿用C语言数组内存分配逻辑判断。

敬慕百科汇集百科知识与游戏文化,带你发现世界的每一个精彩角落。

想要了解更多关于数组在内存中如何分配的文章欢迎访问:百科