我对这里的差异感到有些困惑,在C99:
int myfunc (int array[n], int n) { ... }
不会编译。据我所知,你必须首先将引用放在数组大小,所以必须写入:
int myfunc (int n, int array[n]) { ... }
但是如果你提供静态关键字,这绝对没问题:
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;
}
答案 0 :(得分:8)
原因
int myfunc (int n, int array[n]) { ... }
有效且
int myfunc (int array[n], int n) { ... }
不是由于C的词法范围规则。在范围中引入标识符之前不能使用该标识符。这个规则有一些例外,但这个规则不是其中之一。
编辑:这是C标准的相关段落:
(C99,6.2.1p7)“任何其他标识符的范围都在其声明者完成之后开始。”
此规则也适用于函数原型范围内的参数声明。
答案 1 :(得分:2)
已经向您解释了出错的原因:您必须在之前声明n
,您可以在其他声明中使用它。
然而,值得注意的是,这些声明中没有一个实际上声明了可变长度数组,正如您似乎相信的那样。
确实,在C99中首先允许使用[n]
的语法,并且它正式是VLA声明,但在给定的上下文中,所有这些声明都将array
声明为{int *
的参数1}}类型,就像它一直在C89 / 90中一样。 [n]
部分不是任何形式的暗示。您可以在此声明中使用[n]
这一事实确实是VLA支持的副作用,但这是与VLA的任何关系结束的地方。 <{1}}被忽略了。
“提示”声明需要[n]
内的关键字static
。因此,您使用[]
的声明等同于经典[static 1]
声明(意味着int array[1]
被忽略且参数具有类型1
),除了它为编译器提供了一个提示至少int *
元素必须存在于1
指向的内存位置。
答案 2 :(得分:1)
这是因为数组必须使用常量值声明,因此您无法使用可变大小创建数组,因此无法传递具有可变大小的数组。另外,如果它只是一个单维数组,你根本不需要传入一个值,这就是传递第二个参数来告诉你数组的长度。
要使其正常工作,只需编写如下函数标题:
int myfunc (int myArray[], int n) {...}
顺序无关紧要,但是你传递的数组的大小不能变化,它必须是一个常量值。
答案 3 :(得分:1)
如果您正在使用GCC并且愿意使用他们的某些扩展程序,那么您可以在此处完成您的工作:
int myFunc (int len; /* notice the semicolon!! */ int data[len], int len)
{
}
此扩展程序的文档(可变长度数组)为here。
请注意,clang由于某种原因,此扩展程序不可用,但我不太确定原因。
答案 4 :(得分:0)
编辑:Derp,范围,当然。
我的问题是;为什么你需要这样做?无论如何,你真的得到一个指针(你无法将数组传递给C中的函数,它们会降级为指针,无论函数的签名如何)。它有助于让调用者知道输入的预期大小,但除此之外它是无用的。由于他们已经超过了大小,只需使用...
int myfunc(int arr[], size_t size) {
// ...
}
或者
int myfunc(int *arr, size_t size) {
// ...
}