9

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

void sort(int s, int e, int arr[*]){
    ...
}

它说对于可变长度数组,它需要在函数声明中限定。这意味着什么?我正在使用带有 LLVM 编译器 2.0 的 xcode 4.0。

谢谢您的帮助。

4

4 回答 4

28

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

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

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

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

}

相当于

void sort(size_t n, int *arr){

}

更高的维度很好地传递给函数

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

}

相当于

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

}

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

现在出现了您发现的语法,该语法仅对原型有用,您可以在其中前向声明函数的接口

void toto(size_t, size_t, int arr[*][*]);

*所以在这里你可以用占位符替换数组维度。但这仅在您手头没有维度名称时才有用,并且使用与定义完全相同的版本会更清楚。

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

通常,为了始终如一地使用它,在参数列表中首先拥有尺寸非常重要。否则当编译器解析arr.

于 2011-08-29T06:11:57.423 回答
2

你想做什么让你的论点成为一个int *;传入数组的长度(调用者可能知道,但这个例程不知道)作为单独的参数。您可以将数组作为这样的参数传递。

于 2011-08-29T01:55:17.970 回答
2

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

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

#include <stdio.h>

static void fn (int *arr, size_t start, size_t end) {
    size_t idx;
    for (idx = start; idx <= end; idx++) {
        printf ("%d ", arr[idx]);
    }
    putchar ('\n');
}

int main (void) {
    int my_array[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
    fn (my_array, 4, 6);
    return 0;
}

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

5 4 3

有几点需要注意。

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

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


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

所以,虽然:

void xyzzy(int, int[*]);

是有效的,以下是无效的:

void xyzzy(int sz, int plugh[*]) { doSomething(); }

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

void xyzzy(int sz, int plugh[sz]) { doSomething(); }

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

错误:除函数原型范围外不允许“[*]”

于 2011-08-29T02:04:26.037 回答
1

可变长度数组的数组括号内的使用*仅限于原型,并且仅用作占位符。稍后定义函数时,数组的大小应存储在文件范围内可用的变量中或作为参数之一。这是一个简单的例子:

void foo(int, int[*]);
/* asterisk is placeholder */

void foo(int size, int array[size]) {
/* note size of array is specified now */
}
于 2015-07-22T16:31:34.273 回答