在函数中使用可变长度数组作为参数时
int sum(int n, int a[n]);
很容易理解第一个参数(n
)指定第二个参数()的长度a
。但是遇到了另一个用于VLA作为参数 的原型
int sum(int n, int a[*]);
真的很难理解,为什么里面*
用的是代替?n
[]
在函数中使用可变长度数组作为参数时
int sum(int n, int a[n]);
很容易理解第一个参数(n
)指定第二个参数()的长度a
。但是遇到了另一个用于VLA作为参数 的原型
int sum(int n, int a[*]);
真的很难理解,为什么里面*
用的是代替?n
[]
该[*]
语法旨在在声明函数原型时使用。这里的关键细节是在函数原型中你不需要命名参数,你只需要指定每个参数的类型。
在您的示例中,如果您将第一个参数保留为unnamed,那么显然您将无法n
在第二个(数组)参数声明中使用。然而,在许多情况下,您必须告诉编译器某些参数是 VLA。这时候[*]
语法就派上用场了。
在您的情况下,如果您省略参数名称,原型可能看起来像
int sum(int, int [*]);
但是,重要的是要注意,在您的特定示例中,此语法是合法的,但并非完全必要。就像非 VLA 数组一样,int [n]
参数仍然等同于int *
参数(即使对于非常量n
)。这意味着您可以简单地将您的功能原型化为
int sum(int, int []);
或作为
int sum(int, int *);
并且原型仍将发挥其作用,即它将正确匹配函数定义。换句话说,声明为一维数组的参数的 VLA 属性完全无关紧要,并且[*]
此类 VLA 数组并不真正需要该功能。
[*]
在类型的“可变数组”不丢失的情况下,这变得很重要,就像 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 的方法,用*
代替变量名。极简主义
这里的问题是,如果你为 VLA 放置一个变量而不是星号,它会告诉你它是未声明的,所以星号是 c99 内置的一种解决方法。