4

在 C99 中,我对这里的区别有点困惑:

int myfunc (int array[n], int n) { ... }

不会编译。据我所知,您必须始终将对数组大小的引用放在首位,因此必须编写:

int myfunc (int n, int array[n]) { ... }

但是,如果您提供 static 关键字,这绝对可以正常工作:

int myfunc (int array[static 1], int n) { ... }

这个顺序对我来说更可取,因为我习惯于在函数调用中将数组放在第一位,但为什么会这样呢?

编辑:意识到第三个示例实际上不是 VLA 有助于...

作为参考,这是我正在查看的导致问题的代码:

int sum_array(int n, int m, int a[n][m])
{
  int i, j, sum = 0;
  for (i = 0; i < n; i++)
    for (j = 0; j < m; j++)
      sum += a[i][j];
  return sum;
}
4

5 回答 5

8

之所以

int myfunc (int n, int array[n]) { ... }

有效并且

int myfunc (int array[n], int n) { ... }

不是由于 C 的词法范围规则。标识符在被引入范围之前不能使用。这条规则有一些例外,但这不是其中之一。

编辑:这是C标准的相关段落:

(C99,6.2.1p7)“任何其他标识符的范围都在其声明符完成后开始。”

此规则也适用于函数原型范围内的参数声明。

于 2012-08-30T22:03:36.540 回答
2

错误的原因已经给你解释过了:你必须先声明n ,然后才能在其他声明中使用它。

然而,值得注意的是,这些声明都没有真正声明可变长度数组,正如您所相信的那样。

的确,with 语法[n]首先在 C99 中被允许,并且它正式是一个 VLA 声明,但是在给定的上下文中,所有这些声明都声明arrayint *类型参数,就像在 C89/90 中一样。这[n]部分不是任何形式的暗示。您可以[n]在此声明中使用的事实确实是 VLA 支持的副作用,但这是与 VLA 的任何关系结束的地方。这[n]被简单地忽略了。

“提示”声明需要static[]. 因此,您的声明[static 1]等同于经典int array[1]声明(意味着1被忽略并且参数具有 type int *),除了它向编译器提示至少1元素必须存在于指向的内存位置array

于 2012-08-30T22:07:49.870 回答
1

这是因为数组必须用常量值声明,因此您不能使用可变大小创建数组,因此不能传递具有可变大小的数组。此外,如果它只是一个单维数组,您根本不需要传递值,那就是传递第二个参数来告诉您数组的长度。

为了让它正常工作,只需像这样编写函数头:

int myfunc (int myArray[], int n) {...}

顺序无关紧要,但是您不能将要传递的数组的大小设置为变量,它必须是一个常量值。

于 2012-08-30T21:58:44.500 回答
1

如果你正在使用 GCC 并且愿意使用他们的一些扩展,你可以在这里完成你想要的:

int myFunc (int len; /* notice the semicolon!! */ int data[len], int len)
{

}

此扩展(可变长度数组)的文档在此处

请注意,由于某种原因,这个扩展在clang中不可用,不过我不太确定为什么。

于 2012-08-30T22:07:40.260 回答
-1

编辑:Derp,范围,当然。

我的问题是;为什么你需要这样做?无论如何,您确实得到了一个指针(您不能将数组传递给 C 中的函数,它们会降级为指针,而不管函数的签名如何)。它有助于让调用者知道输入的预期大小,但除此之外它就没用了。由于他们已经通过了大小,只需使用...

int myfunc(int arr[], size_t size) {
    // ...
}

或者

int myfunc(int *arr, size_t size) {
    // ...
}
于 2012-08-30T21:57:46.890 回答