scanf("%d %d", &a, &b);
double array1[a][b];
这在 C99 标准中是有效的,尽管您需要先对输入进行一些健全性检查(即,确保两个输入都被实际读取,确保两者都不是负数,确保它们在合理范围等)。
array1 是一个可变长度数组 (VLA),最初是在 C99 中引入的。自 C2011 起,它们已成为可选,但我认为几乎所有托管实现仍然支持它们。为确保这一点,请检查 __STDC_NO_VLA__ 宏 - 如果已定义,则实现不支持 VLA。
size_t a, b;
if ( scanf( "%zu %zu", &a, &b ) < 2 )
// bail out with an error message
#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L && !defined( __STDC_NO_VLA__ )
/**
* This implementation supports VLAs. We need to do an additional
* sanity check on a and b to make sure we don't allocate an
* object too large for the stack (even though VLAs
* don't have to be allocated on the stack, that's how many
* implementations choose to do it).
*/
if ( a > SOME_MAX_LIMIT || b > SOME_MAX_LIMIT )
// bail out with an error
double array1[a][b];
#else
/**
* This implementation does not support VLAs, so we'll have to use
* dynamic memory allocation. Note that memory allocated this way
* is *not* contiguous - rows are not adjacent, so the object immediately
* following array1[0][b-1] is not array1[1][0]. If that matters,
* then this won't work.
*/
double **array1 = malloc( sizeof *array1 * a );
if ( array1 )
{
size_t i;
for ( i = 0; i < a; i++ )
{
array1[i] = malloc( sizeof *array1[i] * b );
if ( !array1[i] )
break;
}
if ( i < a ) // memory allocation failure, clean up any previously allocated memory
{
while ( i-- )
free( array1[i] );
free( array1 );
// bail out with an error here
}
}
else
// memory allocation failed, bail with an error
#endif
此时,您的代码可以引用array1[i][j],无论我们以哪种方式分配它。但是,您需要在函数末尾添加:
#if !defined( __STDC_VERSION__ ) || __STDC_VERSION__ < 199901L || defined( __STDC_NO_VLA__ )
for ( size_t i = 0; i < a; i++ )
free( array1[i] );
free( array1 );
#endif
以便我们在必须使用 malloc 时自行清理。
VLA 的行为与其他所有 auto(本地)数组非常相似 - 当您退出函数时,它们的内存将被释放,因此您不能返回指向它们的指针并让指针在函数之后有效退出。
由于它们的大小直到运行时才确定,所以不能在文件范围内使用它们(在任何函数之外),不能将它们声明为 static,并且它们不能是 struct 的成员或union 类型。
您可以将 VLA 与动态内存分配结合起来:
size_t a, b;
if ( scanf( "%zu %zu", &a, &b ) < 2 )
// bail out with an error
double (*array1)[b] = malloc( sizeof *array1 * a );
您将获得一个动态分配的二维数组,该数组具有用户指定的维度, 是连续的,并且您仅受堆大小的限制,而不是堆栈大小,因此您可以通过此分配大对象大大地。