深⼊理解C语⾔数组与内存分配
深⼊理解C语⾔数组与内存分配
C语⾔在定义数组时是否允许使⽤变量指定数组长度,如果您的答案否,那我建议您仔细阅读以下这篇⽂章:)
概述
很多C语⾔教材都提到数组长度的定义必须是常量,为什么C语⾔数组会有这种限制呢?这就要从程序变量的内存分配开始说起了。
我么知道程序在运⾏时候数据、变量可能会存放的段有以下⼏个:
堆区:malloc分配的内存就在这个区中
栈区:程序调⽤时函数内部的局部变量在这个区中
.data区:这个区中的数据是程序开始运⾏前由操作系统的加载器将可执⾏⽂件加载进⼊内存时创建的,⽤于存放程序中定义的已初始化全局变量或者静态变量。
回到刚刚的问题,数组会存放到哪⼏个段中呢?
这个可能要和数组的位置有关系了,我们分成⼏种情况讨论。
定义为函数内局部变量
如果数组定义成函数中的局部变量,⽐如下⾯的代码:
molloc函数void f1(int n)
{
int array[n];
int i;
for(i =0; i < n; i++)
{
array[i]= i;
}
}
int main()
{
f1(1024);
}
代码中的数组,属于函数f1内的局部变量,根据概述中的描述应该内存应该开辟在栈中。
栈中的变量有⼀个很重要的特性就是当函数返回的后,变量占⽤的内存会被释放。结合栈的FILO的特性,对于⼀个函数如果需要申请临时变量仅仅需要将栈指针移动就很⽅便的为变量申请了空间。
回到这个问题如果在函数内部定义⼀个数组,⽽数组的长度是不固定的,长度是由参数n决定的是否可⾏呢?
答案是可⾏的,仅仅需要程序在运⾏时将程序传⼊的变量n*数组每个元素的长度就可以得出数组的长
度。然后移动堆栈指针SP 数组长度就为数组分配出了内存。
事实上c89之后的编译器也的确允许这样定义。
这个特性相对于使⽤malloc函数还是有好处的,
1. 不需要程序员考虑内存管理,不会造成内存泄漏。
2. 效率相对于malloc的伙伴算法会快
3. 不会造成内存碎⽚
定义为函数内静态变量
如果数组定义成函数内的静态变量,⽐如下⾯的代码:
void f1(int n)
{
static int array[n];
int i;
for(i =0; i < n; i++)
{
array[i]= i;
}
}
int main()
{
f1(1024);
}
静态变量的内存时在程序加载时分配在.data段的,由于此时程序尚未运⾏,不能确定函数参数n的值,⽆法确定申请内存的⼤⼩。因此这种情况编译器不能通过。我们尝试拿该代码编译会报错
test.c:8:13: error: storage size of ‘array’ isn’t constant
static int array[n];
定义为全局变量
如果数组定义成全局变量呢,⽐如下⾯的代码:
int size =10;
int array[size];
void f1(int n)
{
int i;
for(i =0; i < n; i++)
{
array[i]= i;
}
}
int main()
{
f1(1024);
}
全局变量内存空间的申请也是需要在程序加载初期由加载器初始化,这种情况下的数组内存分配到.data段中,基于上段相似的理由,编译器⽆法⽀持,会报如下错误:
test.c:5:5: error: variably modified ‘array’ at file scope
int array[size];
^
结论
C语⾔在定义数组时是否允许使⽤变量指定数组长度呢?
答案是分情况,
如果数组定义在函数内部时,编译器会⼒所能及的帮我们实现变量长度定义数组。
其他的情况由于内存空间在程序加载时就需要知道数组占⽤的空间⼤⼩,所以编译器⽆计可施只能报错。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论