为什么使用星号“”代替函数的VLA数组参数的整数?

在函数中使用变长数组作为参数时

int sum(int n, int a[n]); 

第一个参数( n )指定第二个参数( a )的长度,这很容易理解。 但遇到另一个用于VLA的原型作为参数

 int sum(int n, int a[*]); 

真的很难理解,为什么在[]使用而不是n

在声明函数原型时,将使用[*]语法。 这里的关键细节是在函数原型中,你不需要命名你的参数,你只需要指定每个参数的types。

在你的例子中,如果你留下第一个参数未命名 ,那么显然你不能在你的第二个(数组)参数声明中使用n 。 然而,在许多情况下,你必须告诉编译器,一些参数是VLA。 这是当[*]语法来救援。

在你的情况下,如果你省略参数名称,原型可能看起来像

 int sum(int, int [*]); 

然而,重要的是要注意,在你的具体例子中,这个语法是合法的,但并不是完全必要的。 就像使用非VLA数组一样, int [n]参数仍然等于int *参数(即使对于非常量n )。 这意味着你可以简单地将你的函数原型化为

 int sum(int, int []); 

或如

 int sum(int, int *); 

原型仍然会达到它的目的,即它将正确匹配函数定义。 换句话说,声明为一维数组的参数的VLA属性是完全无关紧要的,并且这种VLAarrays并不需要[*]特性。

在types的“可变数组性”不会丢失的情况下, [*]就变得很重要,就像2D VLA(或者指向VLA的指针)那样。 例如定义为的函数

 int sum2d(int n, int m, int a[n][m]) { ... } 

可能是以下任何一种原型

 int sum2d(int, int, int a[*][*]); int sum2d(int n, int, int a[n][*]); int sum2d(int, int m, int a[*][m]); int sum2d(int n, int m, int a[n][m]); 

以上所有原型都与函数定义正确匹配。

当然,如果你习惯于在函数原型中总是命名所有的参数,那么你将永远不需要这个语法,因为你可以使用上面列表中的最后一个原型。

PS同样,与参数声明中所有数组的情况一样,第一个[]总是无关紧要,总是衰减到一个指针,这意味着以下也是上述sum2d有效等价原型声明

  int sum2d(int, int, int a[][*]); int sum2d(int, int, int (*a)[*]); int sum2d(int n, int m, int (*a)[m]); 

这是第二个真正重要的,必须被宣布为“可变长度”。

当你把星形放在一个实际的函数中时,会给出这个错误test.c:3: error: '[*]' not allowed in other than function prototype scope 。 经过一番研究,这实际上是一种在函数原型中声明VLA的方法,用*代替variables名。 VLA 。
这里的问题在于,如果你为VLA放置一个variables而不是星号,它会告诉你它没有被声明,所以这个星号是一个用来解决这个问题的方法。