变长数组 VLA
变长数组(Variable Length Array,VLA)是 C99 引入的特性,允许数组大小在运行时确定。VLA 分配在栈上,适合需要动态大小但不想用堆分配的场景。C11 将 VLA 改为可选特性,但大多数编译器仍支持。
基本用法
void process(int n)
{
int arr[n]; /* VLA:大小由参数决定 */
for (int i = 0; i < n; i++)
arr[i] = i;
/* 使用 arr */
/* 函数返回时自动释放 */
}
process(100); /* 分配 100 个 int */
process(1000); /* 分配 1000 个 int */
多维 VLA
void matrix_multiply(int m, int n, int p,
int A[m][n],
int B[n][p],
int C[m][p])
{
for (int i = 0; i < m; i++)
for (int j = 0; j < p; j++) {
C[i][j] = 0;
for (int k = 0; k < n; k++)
C[i][j] += A[i][k] * B[k][j];
}
}
VLA 与指针
void print(int rows, int cols, int arr[rows][cols])
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
}
限制
void func(int n)
{
int arr[n]; /* VLA 在栈上 */
/* 不能 static */
/* static int bad[n]; */ /* 错误 */
/* 不能 extern */
/* extern int bad2[n]; */ /* 错误 */
/* 不能用于结构体成员 */
/* struct { int arr[n]; } s; */ /* 错误 */
}
常见错误
栈溢出:
void func(int n)
{
int arr[n]; /* n 很大时栈溢出 */
/* ... */
}
func(1000000); /* 可能栈溢出:4MB */
sizeof 运行时求值:
int n = 10;
int arr[n];
size_t s = sizeof(arr); /* 运行时计算:40 */
/* 与固定大小数组不同 */
int fixed[10];
size_t s2 = sizeof(fixed); /* 编译时计算:40 */
最佳实践
- 小数组用 VLA,大数组用堆分配
- 检查大小防止栈溢出
- 注意
sizeof(VLA)是运行时计算 - C11 起 VLA 是可选的,需要可移植性时避免
- 多维数组参数用 VLA 语法提高可读性