为什么使用星号“”代替函数的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而不是星号,它会告诉你它没有被声明,所以这个星号是一个用来解决这个问题的方法。