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

时间:2018-09-23 10:40:15

标签: c arrays function arguments sizeof

#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函数的参数?

3 个答案:

答案 0 :(得分:3)

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

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

  • 您在原始代码中所做的工作。
  • 将长度作为另一个参数。
  • 包括长度作为数组元素。
  • 在数组末尾具有一个哨兵值。

最常见的习惯用法是传递int *p, size_t n,在没有给出维数的情况下,使用数组指针并不能真正获得任何收获。

答案 1 :(得分:2)

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

在“现代C”中(即将近20年),您可能为此使用了可变长度数组-您可以将size用作参数,然后再传递数组:

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

打字少。

答案 2 :(得分:0)

简短答案: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将始终返回指针的大小