浅谈c语言数组及可变长数组

您所在的位置:网站首页 数组长度有限制吗 浅谈c语言数组及可变长数组

浅谈c语言数组及可变长数组

2024-01-07 07:30| 来源: 网络整理| 查看: 265

1,了解C89标准和C99中数组的区别

以下摘自C89标准和C99标准C11标准的区别

对数组的增强–可变长数组   C99中,程序员声明数组时,数组的维数可以由任一有效的整型表达式确定,包括只在运行时才能确定其值的表达式,这类数组就叫做可变长数组,但是只有局部数组才可以是变长的.可变长数组的维数在数组生存期内是不变的,也就是说,可变长数组不是动态的.可以变化的只是数组的大小.可以使用*来定义不确定长的可变长数组。

因此,windows上不支持以下程序(c98?),但linux gcc就支持(c99),仅仅是因为它们的编译器支持不同的标准,下面我们说那个标准不支持更准确:

int b; int a[b]; # c98和c99都不支持这种 void test2(int n) { //scanf("%d", &n); int a[n];# c98不支持,c99支持,谭浩强说支持但实测的不支持,又是标准惹的祸吧 a[0] = 1; printf("%d\n", a[0]); } int main() { int a = 43; test2(a); # c98不支持,c99支持 return 0; }

以下摘自C99可变长数组VLA详解

在程序设计过程中,我们常常遇到需要根据上下文环境来定义数组的情况,在运行期才能确知数组的长度。对于这种情况,C90及C++没有什么很好的办法去解决(STL的方法除外),只能在堆中创建一个内存映像与需求数组一样的替代品,这种替代品不具有数组类型,这是一个遗憾。C99的可变长数组为这个问题提供了一个部分解决方案。可变长数组(variable length array,简称VLA)中的可变长指的是编译期可变,数组定义时其长度可为整数类型的表达式,不再象C90/C++那样必须是整数常量表达式。

2,变长数组很方便,但为什么还是建议有限制地使用?

以下内容整理自C语言为什么不建议把变量作为数组长度 (1)支持VLA(变长数组)的编译器都大多数在栈上分配,但也有在堆上分配的,如armcc的VLA默认是直接使用系统的malloc,free来实现的,据说armcc的VLA用堆还是用栈是可以配置的,我没有深究,若你不确定你的编译器会以何种方式生成VLA代码的时候,不要假定它是基于栈实现的。这是一个比较容易出BUG的点。要避免这种BUG的方式其实也很简单,那就是避免使用VLA。即当要分配的空间长度上界比较小时,你可以使用固定数组大小的形式分配,浪费一点点不用也没关系;当你要分配空间的长度的上界比较大时,直接使用动态分配malloc等函数。

(2)因为这里面有太多的坑了,如果你不明白其中原理的话,那么你很容易掉坑里面。变长数组的实现是通过动态设置栈顶来实现的,也就是说这个东西还是在栈上而不是在堆里,这就带来了问题:第一,因为栈的大小是有限制的所以你的每次动态声明相当于调用了一次alloca,不知道这东西的可以自己去查下,其实他们的原理是一样的,通过设置栈顶在栈空间分配一块空间。所以动态数组不能太大。第二,这个东西因为实现在栈上面所以跟栈相关的操作都跟他互相有影响,比如上面提到的alloca,这个东西于动态数组的区别在于作用域,alloca在分配在函数内有效,但是动态数组在最内层括号内有效。但是(这里是重点),因为他们都在栈上面,所以一旦动态数组失效后,在其后分配的alloca也会被free,所以会产生很多不可预料的问题。比如这段代码:

int test() { int a = 10; char *c; { char b[a]; a = 8 * 1024; c = alloca(a); } char d[a]; memset(c, 0, a); memset(d, 2, a); return c[0]; }

编译运行你会得到一个core dump 以下通过在堆上动态申请空间来替代VAL. malloc(sizeof(Type) * number)… calloc(sizeof(Type), number) p = malloc (sizeof (*p) *number)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3