为什么我们不能使用 const int 来初始化 char 数组的大小?

Why can we not use an const int to initialize the size of a char array?

以下代码片段在 C 中是非法的,但在 C++ 中可以完美运行。

为什么我们不能在 C 中使用 const 来帮助初始化数组的长度?

#include <stdio.h>
#include <string.h>

int main () {

   const int size = 6;
   char name[size] = "hello";
   printf("%s", name);

   return 0;
}

C 标准允许 C 编译器支持可变长度数组。用作数组大小的变量的 const 限定符不会在 C 中生成与 C++ 相反的常量整数表达式。

来自 C 标准(6.6 常量表达式)

6 An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.

这句话中的整数或字符常量表示文字。

至于可变长度数组 (The C Standard 6.7.6.2 Array declarators)

4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope; such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)

一些 C++ 编译器可以有自己的语言扩展,允许在 C++ 程序中使用可变长度数组。但它不是 X++ 标准功能。

即使 C++ 编译器支持可变长度数组,也最好使用标准 class 模板 std::vector 而不是可变长度数组。

注意在声明时不能在 C 语言中初始化变长数组。并且可变长度数组具有自动存储持续时间。您可以将 sizeof 运算符应用于在 run-time.

处计算的可变长度数组

这是一个使用可变长度数组的演示程序。

#include <stdio.h>

void f( size_t, size_t, int[][*] );

void f( size_t m, size_t n, int a[][n] )
{
    for ( size_t i = 0; i < m; i++ )
    {
        for ( size_t j = 0; j < n; j++ )
        {
            a[i][j] = n * i + j;
        }
    }
}

void g( size_t, size_t, int[][*] );

void g( size_t m, size_t n, int a[][n] )
{
    for ( size_t i = 0; i < m; i++ )
    {
        for ( size_t j = 0; j < n; j++ )
        {
            printf( "%2d ", a[i][j] );
        }
        putchar( '\n' );
    }
}

int main(void) 
{
    const size_t m1 = 3, n1 = 3;
    int a[m1][n1];
    
    f( m1, n1, a );
    g( m1, n1, a );
    
    putchar( '\n' );
    
    const size_t m2 = 4, n2 = 5;
    int b[m2][n2];
    
    f( m2, n2, b );
    g( m2, n2, b );
    
    putchar( '\n' );
    
    return 0;
}

程序输出为

 0  1  2 
 3  4  5 
 6  7  8 

 0  1  2  3  4 
 5  6  7  8  9 
10 11 12 13 14 
15 16 17 18 19

在C语言中,大小不是整数常量表达式的数组是变长数组,这样的数组不能初始化因为在编译时不知道它们的大小。

具有 const 限定符的变量 算作 C 中的整型常量表达式,因此 name 成为可变长度数组,结果为尝试初始化时的错误。

另一方面,C++ 对常量有不同的规则。 const 限定变量,其初始值设定项是整数常量表达式 在 C++ 中被视为编译时常量,因此可以初始化使用此类变量指定其大小的数组。