我正在尝试编写一个函数,该函数在 c 中采用可变大小的数组。
void sort(int s, int e, int arr[*]){
...
}
它说对于可变长度数组,它需要在函数声明中限定。这意味着什么?我正在使用带有 LLVM 编译器 2.0 的 xcode 4.0。
谢谢您的帮助。
我正在尝试编写一个函数,该函数在 c 中采用可变大小的数组。
void sort(int s, int e, int arr[*]){
...
}
它说对于可变长度数组,它需要在函数声明中限定。这意味着什么?我正在使用带有 LLVM 编译器 2.0 的 xcode 4.0。
谢谢您的帮助。
我看到没有人回答真正的问题,在这里我给出我的。
在 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
.
你想做什么让你的论点成为一个int *
;传入数组的长度(调用者可能知道,但这个例程不知道)作为单独的参数。您可以将数组作为这样的参数传递。
如果您不使用 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
有相当清晰的错误消息,比您看到的“需要在函数声明中限定”要好得多:
错误:除函数原型范围外不允许“[*]”
可变长度数组的数组括号内的使用*
仅限于原型,并且仅用作占位符。稍后定义函数时,数组的大小应存储在文件范围内可用的变量中或作为参数之一。这是一个简单的例子:
void foo(int, int[*]);
/* asterisk is placeholder */
void foo(int size, int array[size]) {
/* note size of array is specified now */
}