C语言中的变长数组



C语言中的变长数组也称为变尺寸数组或运行时尺寸数组。它是一个长度在运行时确定而不是在编译程序时确定的数组。其大小取决于程序运行期间生成的、通常从用户那里接收到的输入值。

通常,数组大小在程序中预先声明如下:

int arr[10];

一旦声明,数组的大小在程序执行期间保持固定,并且不能在运行时更改。但是,对于变长数组(VLA),编译器会在堆栈上分配具有自动存储期的内存。对VLA的支持是在C99标准中添加的。

创建变长数组

创建变长数组的语法如下:

void arr_init(int length){

   int arr[length];

   //code using arr;

};

示例

下面的例子演示了如何创建一个变长数组:

#include <stdio.h>

int main(){

   int i, j;
   int size; // variable to hold size of one-dimensional array

   printf("Enter the size of one-dimensional array: ");
   scanf("%d", &size);

   int arr[size];
   
   for(i = 0; i < size; ++i){
      printf("Enter a number: ");
      scanf("%d", &j);
      arr[i] = j;
   }

   for(i = 0; i < size; ++i)
   printf("a[%d]: %d\n", i, arr[i]);

   return 0;
}

输出

运行这段代码时,它会要求你输入数组的大小。请注意,数组的长度在声明时不是固定的。你可以在运行时定义其大小。

Enter the size of one-dimensional array: 5
Enter a number: 1
Enter a number: 5
Enter a number: 7
Enter a number: 8
Enter a number: 7

a[0]: 1
a[1]: 5
a[2]: 7
a[3]: 8
a[4]: 7

二维变长数组

我们还可以声明和使用二维变长数组。

示例1

看下面的例子:

#include <stdio.h>

int main(){

   int i, j, x;
   
   int row, col; // number of rows & columns of two D array

   printf("Enter number of rows & columns of 2-D array:\n");
   scanf("%d %d", &row, &col);

   int arr2D[row][col];
   for(i = 0; i < row; ++i){
      for(j = 0; j < col; ++j){
         printf("Enter a number: ");
         scanf("%d", &x);
         arr2D[i][j] = x;
      }
   }

   for(i = 0; i < row; ++i){
      printf("\n");
      for(j = 0; j < col; ++j)
         printf("%d\t", arr2D[i][j]);
   }

   return 0;
}

输出

运行代码并检查其输出:

Enter number of rows & columns of 2-D array:
2
3
Enter a number: 10
Enter a number: 20
Enter a number: 30
Enter a number: 40
Enter a number: 50
Enter a number: 60
10	20	30	
40	50	60

示例2

以下代码声明一个变长的一维数组,并用递增的数字填充它:

#include <stdio.h>

int main(){

   int n;
    
   printf("Enter the size of the array: \n");
   scanf("%d", &n);
    
   int arr[n];
    
   for(int i = 0; i < n; i++)
      arr[i] = i+1;
    
   printf("The array elements are: ");

   for(int i = 0; i < n; i++)
      printf("%d ", arr[i]);
    
   return 0;
}

输出

运行代码并检查其输出:

Enter the size of the array: 
5
The array elements are: 1 2 3 4 5 ....

示例3

以下代码使用来自`stdlib.h`头文件的`srand()`和`rand()`函数,用随机生成的数字填充变长数组。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void oneDArray(int length, int a[length]); 

// function prototype
void twoDArray(int row, int col, int a[row][col]);

// function prototype
int main(){

   int i, j; 
   
   // counter variable
   int size; 
   
   // variable to hold size of one dimensional array
   int row, col; 
   
   // number of rows & columns of two D array
   srand(time(NULL));
   
   printf("Enter the size of one-dimensional array: ");
   scanf("%d", &size);
   
   printf("Enter the number of rows & columns of 2-D array:\n");
   scanf("%d %d", &row, &col);

   // declaring arrays
   int arr[size];
   
   // 2-D array
   int arr2D[row][col]; 

   // one dimensional array
   for(i = 0; i < size; ++i){
      arr[i] = rand() % 100 + 1;
   }

   // two dimensional array
   for(i = 0; i < row; ++i){
      for(j = 0; j < col; ++j){
         arr2D[i][j] = rand() % 100 + 1;
      }
   }

   // printing arrays
   printf("One-dimensional array:\n");
   
   // oneDArray(size, arr);
   for(i = 0; i < size; ++i)
   printf("a[%d]: %d\n", i, arr[i]);
   printf("\nTwo-dimensional array:\n");
   
   // twoDArray(row1, col1, arr2D);
   for(i = 0; i < row; ++i){
      printf("\n");
      for (j = 0; j < col; ++j)
         printf("%5d", arr2D[i][j]);
   }
}

输出

运行代码并检查其输出:

Enter the size of one-dimensional array: 5
Enter the number of rows & columns of 2-D array:
4 4
One-dimensional array:
a[0]: 95
a[1]: 93
a[2]: 4
a[3]: 52
a[4]: 68

Two-dimensional array:
   92   19   79   23
   56   21   44   98
    8   22   89   54
   93    1   63   38

锯齿数组

锯齿数组是两个或多个具有相同数据类型但长度可变的数组的集合。在C语言中,锯齿数组的概念是借助于数组指针实现的。

锯齿数组由下图表示:

A Jagged Array

示例

在这个程序中,我们声明了三个大小不同的单维数组,并将它们的指针存储在一个指针数组中,该指针数组充当锯齿数组。

#include <stdio.h>

int main(){

   int a[] = {1,2};
   int b[] = {3,4,5};
   int c[] = {6,7,8,9};
   
   int l1 = sizeof(a)/sizeof(int), 
   l2 = sizeof(b)/sizeof(int), 
   l3 = sizeof(c)/sizeof(int);
   
   int *arr[] = {a,b,c};
   int size[] = {l1, l2, l3};
   int *ptr;
   int i, j, k = 0;

   for(i = 0; i < 3; i++){
      ptr = arr[i];
      for(j = 0; j < size[k]; j++){
         printf("%d\t", *ptr);
         ptr++;
      }
      printf("\n");
      k++;
      arr[i]++;
   }
   
   return 0;
}

输出

运行这段代码时,会产生以下输出:

1       2
3       4       5
6       7       8       9

与堆分配相比,VLA是一种更快、更直接的选择。大多数现代C编译器(如GCC、Clang等)都支持VLA,并且大多数编译器都使用VLA。

广告