为什么不能将 int (*p)[] 用作 C 函数的参数?

Why can't int (*p)[] be used as an argument for C function?

#include <stdio.h>
void print(int (*p)[3]);
int main(void)
{
    int a[3] = {1, 2, 3};
    print(&a);

    return 0;
}
void print(int (*p)[3])
{
    for (int i = 0; i < sizeof(*p) / sizeof(**p); i++)
        printf("%d\n", (*p)[i]);
}

我写了一个C函数。见上文。

它可以打印数组中的所有元素。

有一件事不太完美:数组元素的数量似乎是预先知道的。

所以我做了一些修改,希望能使这个功能通用:

#include <stdio.h>
void print(int (*p)[]);
int main(void)
{
    int a[3] = {1, 2, 3};
    print(&a);

    return 0;
}
void print(int (*p)[])
{
    for (int i = 0; i < sizeof(*p) / sizeof(**p); i++)
        printf("%d\n", (*p)[i]);
}

函数中p是指向整个数组的指针

但是编译失败

为什么不能将 int (*p)[] 用作 C 函数的参数?

int (*p)[] 可以用作函数的参数。代码中给出错误的部分是 sizeof *p,这显然是不可能的,因为 *p 的类型是 int[],这是一个不完整的类型,因此没有已知的大小。

要让函数知道数组的长度,您必须设计一种方法让函数接收此信息。选项包括:

  • 你在原始代码中做了什么。
  • 将长度作为另一个参数传递。
  • 包括作为数组元素的长度。
  • 在数组末尾有一个标记值。

最常见的习惯用法是传递 int *p, size_t n,在没有给出维数的情况下使用指向数组的指针实际上不会获得任何好处。

简短回答:int (*p)[] 不能用作参数并让函数神奇地知道数组大小,因为标准是这么说的。

更长的答案:

int (*p)[] 是指向数组的指针,但数组没有定义大小。所以通过查看数组,不可能进行指针运算,计算 p 指向的东西的大小等。

您没有数组的数组,因此不需要 int (*p)[]。您有一个 int 数组,因此 int *pint p[] 应该足够了。这并不能解决在 print 中知道数组大小的问题。为此,您基本上有 3 个选择

  1. 在函数中硬编码值
  2. 在你的数组中放置一个标记值来标记结束
  3. 像这样将大小作为单独的参数传递:

    void print(int n, int p[n])

请记住,无论您使用什么方法,数组的参数传递在幕后总是使用指针,因此您不能使用 sizeof(p) 来计算数组的大小。 sizeof 在那些情况下总是 return 指针的大小

问题是 int [] 是一个不完整的类型,因为数组没有定义大小,因此无法采用它的 sizeof

在 "modern C" 中(即近 2 个十年)你可以为此使用可变长度数组 - 你可以将大小作为参数传递,然后传递数组:

#include <stdio.h>
#include <stdlib.h>

void print(size_t n, int (*p)[*]);

int main(void) {
    int a[3] = {1, 2, 3};
    print(3, &a);
}

void print(size_t n, int (*p)[n]) {
    for (size_t i = 0; i < sizeof(*p) / sizeof(**p); i++)
        printf("%d\n", (*p)[i]);
}

当然,这对您没有任何好处,因为 sizeof *p / sizeof **pp 将... n。因此我们不妨使用

void print(size_t n, int p[n]) {
    for (size_t i = 0; i < p; i++)
        printf("%d\n", p[i]);
}

打字少