【问题标题】:Is it actually true that when function prototype has a parameter declared as int a[][10] the compiler treats it as int (*a)[10]?当函数原型具有声明为 int a[][10] 的参数时,编译器是否将其视为 int (*a)[10]?
【发布时间】:2026-01-22 20:30:01
【问题描述】:

我听过很多人说,当我们想将一维数组传递给函数fun 时,以下原型是等价的:

1.

   int fun(int a[]);
   int fun(int a[10]);
   int fun(int *a);

我什至听说有人说第一个和第二个在 C 中内部转换为第三个。我猜这是真的,因为在 2 中声明的函数的定义中像 sizeof(a) 那样做会给出大小以字节为单位的指针(而不是 10*sizeof(int))。

话虽如此,我已经看到文本声称将二维数组传递给函数,以下是等效的:

1.

int fun(int a[][10]);
int fun(int (*a)[10]);

在这里,我再次听到人们说在 C 中,第一个在内部转换为第二个。如果是真的,下面应该是等价的吧?

1.

int fun(int a[][]);
int fun(int (*a)[]);

但不幸的是,第一个提出了编译错误,但第二个没有:

    1 | int fun(int a[][]);
      |             ^
t.c:2:13: note: declaration of ‘a’ as multidimensional array must have bounds for all dimensions except the first

这让我觉得C首先将a视为一个多维数组,每个元素都是一个整数数组,但它们的类型不完整(即int[])。

而在第二个中,a 只是一个指向整数数组的指针(未指定大小或类型不完整)。而且两者确实不同,一种格式不等同于另一种……

谁能详细指导我在每种情况下 C 中实际发生的情况?

【问题讨论】:

  • int fun(int (*a)[]); 编译让我感到惊讶

标签: arrays c


【解决方案1】:

首先,声明的规则说数组的元素类型必须是完整的,根据 C 2018 6.7.6.2 1。所以 int a[][] 得到一个编译器错误,因为第一个 [] 指定了一个数组,其元素将是int [],不完整。

解析声明后,将函数参数声明为数组调整为指针,按照 C 2018 6.7.6.3 7.

int (*a)[] 没有错误是允许的,因为没有规定指针必须指向完整类型。 (如果对指针执行算术运算,则指向的类型必须是完整的,根据 C 2018 6.5.6 2 和 3。)

【讨论】:

  • 谢谢,我明白了
  • 澄清一下,After analysis of the declaration 我猜是指After analysis of the declaration by compiler 对吧? [而不是你在C标准中的After analysis of the declaration,你回答的是函数参数的声明......]请你澄清一下。 _/_
  • @AbhishekGhosh:已更新。
【解决方案2】:

相关规则见C17 6.7.6.3/7:

将参数声明为 ''array of type'' 应调整为 ''qualified pointer to type'',其中类型限定符(如果有) 是在数组类型推导的 [ 和 ] 中指定的那些

这有时被非正式地称为“数组衰减”,类似于在表达式中使用数组标识符的规则。


我什至听人说第一个和第二个在 C 中内部转换为第三个

是的,这是正确的,根据上面引用的规则。第一个示例中的所有 3 个声明都是 100% 等效的。


话虽如此,我已经看到声称将二维数组传递给函数的文本是等效的:/--/
在这里,我再次听到人们说在 C 中,第一个在内部转换为第二个。

正确。


int fun(int a[][]); 是一个无效的声明,因为这实际上是一个不完整数组类型的数组,其中每个数组的所有项都是int 的不完整类型。 C 不允许声明具有不完整类型元素的数组。

C17 6.7.6.2/1

元素类型不能是不完整类型或函数类型。

但是,我们可以将最外层的维度保留为不完整的数组类型,因为它无论如何都会被调整为指针,从而使其大小无关紧要。但是根据上述数组元素必须是完整类型的规则,对于内部维度无法做到这一点。 (我们也不能有不完整结构类型的数组。)

int (*a)[] 是有效的,因为它是一个指向不完整类型数组的指针。同样,C 允许我们使用指向不完整结构类型的指针,但我们不能声明不完整结构类型的对象。

【讨论】:

    最近更新 更多