可变长度数组的原型

发布于 2024-12-02 05:57:13 字数 197 浏览 1 评论 0原文

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

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

它表示对于可变长度数组,需要在函数声明中对其进行限制。这意味着什么?我使用 xcode 4.0 和 LLVM 编译器 2.0。

感谢您的帮助。

I am trying to write a function that takes an array of an variable size in c.

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

It says that for variable length arrays, it needs to be bounded in the function declaration. What does that mean? I am using xcode 4.0, with the LLVM compiler 2.0.

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

想你的星星会说话 2024-12-09 05:57:13

由于我发现没有人回答真正的问题,所以我在这里给出我的答案。

在 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 的声明时,它们将无法得知。

As I see that no one answers the real question, here I give mine.

In C99 you have variable length arrays (VLA) that are declare with a length that is evaluated at run time, and not only at compile time as for previous versions of C. But passing arrays to functions is a bit tricky.

A one dimensional array is always just passed as a pointer so

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

}

is equivalent to

void sort(size_t n, int *arr){

}

Higher dimensions are well passed through to the function

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

}

is equivalent to

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

}

With such a definition in the inside of such a function you can access the elements with expressions as arr[i][j] and the compiler knows how to compute the correct element.

Now comes the syntax that you discovered which is only useful for prototypes that is places where you forward-declare the interface of the function

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

so here you may replace the array dimension by * as placeholders. But this is only usefull when you don't have the names of the dimensions at hand, and it is much clearer to use exactly the same version as for the definition.

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

In general for a consistent use of that it is just important that you have the dimensions first in the the parameter list. Otherwise they would not be known when the compiler parses the declaration of arr.

绅刃 2024-12-09 05:57:13

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

下面是一段打印数组范围的代码,类似于您尝试对排序执行的操作。

#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(); }

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

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

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

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

If you're not using the C99 variable length arrays (it appears you are, so see below), the usual solution is to pass in a pointer to the first element, along with any indexes you want to use for accessing the elements.

Here's a piece of code that prints out a range of an array, similar to what you're trying to do with your 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;
}

This outputs elements four through six inclusive (zero-based), giving:

5 4 3

A couple of points to note.

  • Using my_array in that function call to fn automatically "decays" the array into a pointer to its first element. This actually happens under most (not all) circumstances when you use arrays, so you don't have to explicitly state &(my_array[0]).

  • C already has a very good sort function built in to the standard library, called qsort. In many cases, that's what you should be using (unless either you have a specific algorithm you want to use for sorting, or you're doing a homework/self-education exercise).


If you are using real VLAs, you should be aware that the [*] construct is only valid in the function prototype, not in an actual definition of the function.

So, while:

void xyzzy(int, int[*]);

is valid, the following is not:

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

That's because, while you don't need the size parameter in the prototype, you do very much need it in the definition. And, since you have it, you should just use it:

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

The gcc compiler actually has a reasonably clear error message for this, far better than the "needs to be bounded in the function declaration" one you saw:

error: ‘[*]’ not allowed in other than function prototype scope

鲸落 2024-12-09 05:57:13

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

What you want to do it make your argument an int *; pass in the length of the array (which the caller presumably knows, but this routine does not) as a separate argument. You can pass an array as such an argument.

装纯掩盖桑 2024-12-09 05:57:13

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

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

void foo(int size, int array[size]) {
/* note size of array is specified now */
}

The usage of * inside of array brackets for variable-length arrays is limited to prototypes, and serves merely as a placeholder. When the function is later defined, the array's size should be stored in a variable available at either file scope or as one of the parameters. Here's a simple example:

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

void foo(int size, int array[size]) {
/* note size of array is specified now */
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文