可变长度数组的原型

Gre*_*own 6 c arrays variable-length-array

我正在尝试编写一个在c中采用可变大小数组的函数.

void sort(int s, int e, int arr[*]){
    ...
}
Run Code Online (Sandbox Code Playgroud)

它表示对于可变长度数组,它需要在函数声明中有界.那是什么意思?我正在使用xcode 4.0,使用LLVM编译器2.0.

谢谢您的帮助.

Jen*_*edt 24

我看到没有人回答真正的问题,我在这里给我的.

在C99中,您有可变长度数组(VLA),它们的声明长度在运行时进行评估,而且不仅在编译时与C的早期版本一样.但是将数组传递给函数有点棘手.

一维数组总是作为指针传递

void sort(size_t n, int arr[n]) {

}
Run Code Online (Sandbox Code Playgroud)

相当于

void sort(size_t n, int *arr){

}
Run Code Online (Sandbox Code Playgroud)

更高的尺寸很好地传递给了该功能

void toto(size_t n, size_t m, int arr[n][m]){

}
Run Code Online (Sandbox Code Playgroud)

相当于

void toto(size_t n, size_t m, int (*arr)[m]){

}
Run Code Online (Sandbox Code Playgroud)

在这样的函数内部使用这样的定义,您可以使用表达式访问元素,arr[i][j]并且编译器知道如何计算正确的元素.

现在出现了您发现的语法,它只对原型有用,这些原型是您向前声明函数接口的位置

void toto(size_t, size_t, int arr[*][*]);
Run Code Online (Sandbox Code Playgroud)

所以在这里你可以用*占位符替换数组维度.但是,只有当您没有手头的尺寸名称时,这才有用,并且使用与定义完全相同的版本更为清晰.

void toto(size_t n, size_t m, int arr[n][m]);
Run Code Online (Sandbox Code Playgroud)

通常,为了一致地使用它,在参数列表中首先获得尺寸是很重要的.否则,当编译器解析声明时,它们将不会被知道arr.


pax*_*blo 2

如果您没有使用C99 可变长度数组(看起来您是这样,所以请参见下文),通常的解决方案是传递一个指向第一个元素的指针,以及您想要用于访问元素的任何索引。

\n

这是一段打印出数组范围的代码,类似于您尝试对sort.

\n
#include <stdio.h>\n\nstatic void fn (int *arr, size_t start, size_t end) {\n    size_t idx;\n    for (idx = start; idx <= end; idx++) {\n        printf ("%d ", arr[idx]);\n    }\n    putchar (\'\\n\');\n}\n\nint main (void) {\n    int my_array[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};\n    fn (my_array, 4, 6);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这输出元素四到六(从零开始),给出:

\n
5 4 3\n
Run Code Online (Sandbox Code Playgroud)\n

有几点需要注意。

\n
    \n
  • 在该函数调用中使用自动my_arrayfn数组“衰减”为指向其第一个元素的指针。当您使用数组时,这实际上在大多数(不是全部)情况下都会发生,因此您不必显式声明&(my_array[0]).

    \n
  • \n
  • C 已经在标准库中内置了一个非常好的排序函数,称为qsort. 在许多情况下,这就是您应该使用的(除非您有想要用于排序的特定算法,或者您正在做家庭作业/自学练习)。

    \n
  • \n
\n
\n

如果您使用真正的 VLA,您应该注意该[*]构造仅在函数原型中有效,而在函数的实际定义中无效。

\n

所以,同时:

\n
#include <stdio.h>\n\nstatic void fn (int *arr, size_t start, size_t end) {\n    size_t idx;\n    for (idx = start; idx <= end; idx++) {\n        printf ("%d ", arr[idx]);\n    }\n    putchar (\'\\n\');\n}\n\nint main (void) {\n    int my_array[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};\n    fn (my_array, 4, 6);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有效,但以下内容无效:

\n
5 4 3\n
Run Code Online (Sandbox Code Playgroud)\n

这是因为,虽然您在原型中不需要大小参数,但在定义中却非常需要它。而且,既然你有了它,你就应该使用它:

\n
void xyzzy(int, int[*]);\n
Run Code Online (Sandbox Code Playgroud)\n

编译gcc器实际上对此有一个相当清晰的错误消息,比您看到的“需要在函数声明中受到限制”要好得多:

\n
\n

错误:\xe2\x80\x98[*]\xe2\x80\x99 不允许在函数原型范围以外的地方使用

\n
\n

  • 嗯,我没有看到你对这个问题给出了有效的答案。您的答案与 VLA 无关,而是一般描述如何将一维数组传递给函数。这只是图片的一半。 (2认同)