C语言的变长数组

问题背景

写程序的时候经常要定义这样一个数组,要前面程序运行后才能知道要定义数组的大小。

C99之可变长度数组(VLA)

C99:
1994年,由ANSI/ISO联合委员会开始修订C标准
1999年,1994年对C语言的修订引出了ISO 9899:1999的发表,它通常被称为C99
C11:
2011年,国际标准化组织(ISO)和国际电工委员会(IEC) 旗下的C语言标准委员会(ISO/IEC JTC1/SC22/WG14)正式发布了C11标准

c99标准中,新增了可变长度数组:Variable-length array (VLA);C11中VLA变为可选项,不是语言必备的特性。

关于变长数组

变长数组中的“变”不是指可以修改已创建数组的大小,一旦创建了变长数组,它的大小则保持不变。这里的“变”指的是:在创建数组时,可以使用变量指定数组的长度。(普通数组只能用常量或常量表达式指定数组的长度)

  • 变长数组VLA只能是局部变量数组
  • 变长数组VLA不能在定义的时候进行初始化
  • 变长数组VLA必须是自动存储类别,即不能使用extern或static存储类别说明符
  • 变长数组VLA不等于动态数组,本质还是静态数组,也就是说,数组的长度在变量的整个生命周期中是不可变的
  • 由于变长数组只能是局部变量,且必须是自动存储类别,因此变长数组分配在栈上
  • 可变长数组对于多维数组也适用(如array[a][b] )

示例

#include <stdio.h>

int main(void)
{
int a=0;
int b=0;
scanf("%d %d",&a,&b);
char array[a][b];
printf("sizeof(array)=%d\n",sizeof(array));
return 0;
}
上述代码需在支持C99标准的编译器上才行(注意,VS系列编译器均不支持该特性)

根据上面关于数组的几项注意点,下面列出几种错误的示例:

  • int a=2;

  • int b=3;

  • char array1[a][b] = {1,2,3,4,5,6}; //错误,变长数组VLA不能在定义的时候进行初始化

  • char array2[a][b] = {{1,2,3},{4,5,6}}; //错误,变长数组VLA不能在定义的时候进行初始化

  • static char array3[a][b]; //错误,变长数组VLA必须是自动存储类别

关于如果是const变量做数组长度,下面还有几种情况需要思考:

1、在函数体外部,全局数组长度用const类型全局变量,是否可行? – 答:可以。

#include <stdio.h>
const int len = 10;
char array[len];
void main()
{
printf("sizeof(array)=%d\n",sizeof(array));
}

2、在函数体外部,static 全局数组长度用const类型全局变量,是否可行? – 答:可以。

#include <stdio.h>
const int len = 10;
static char array[len];
void main()
{
printf("sizeof(array)=%d\n",sizeof(array));
}

3、在函数体内部,static 局部数组长度用const类型局部变量,是否可行? – 答:可以。

#include <stdio.h>

void main()
{
const int len = 10;
static char array[len];
printf("sizeof(array)=%d\n",sizeof(array));
}

4、在函数体内部,局部数组长度用const类型局部变量,是否可行? – 答:可以。

#include <stdio.h>

void main()
{
const int len = 10;
char array[len];
printf("sizeof(array)=%d\n",sizeof(array));
}

总结:const变量不能直接改变,用其定义数组长度实际上已经不再是变长数组了。