为什么对函数的VLA数组参数使用星号“[*]”而不是整数?

时间:2013-06-28 18:50:53

标签: c arrays function function-parameter

在函数

中使用变长列表作为参数时
int sum(int n, int a[n]);

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

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

真的很难理解为什么在*内使用n代替[]

2 个答案:

答案 0 :(得分:47)

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

在您的示例中,如果您保留第一个参数 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]);

以上所有原型都与函数定义完全匹配。

当然,如果您习惯于始终在函数原型中命名所有参数,那么您将永远不需要这种[*]语法,因为您将能够使用上面列表中的最后一个原型。 / p>

P.S。同样,与参数声明中的所有数组一样,第一个[]始终是无关紧要的并且总是衰减到指针,这意味着以下也是上述sum2d的有效等效原型声明

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

第二个[]确实很重要,必须声明为“可变长度”。

答案 1 :(得分:4)

当您将星形放入实际函数时,会出现此错误test.c:3: error: ‘[*]’ not allowed in other than function prototype scope。经过一些研究,这实际上是一种在函数原型中声明VLA的方法,用*代替变量名。 VLA
这里的问题是,如果你为VLA添加一个变量而不是星号,它会告诉你它是未声明的,所以这个星是c99内置的方式来绕过它。