如何将数组声明为参数不需要为第一维绑定?

时间:2019-07-10 18:02:04

标签: c arrays memory

在C语言中,如果不限制第二个维度,就不可能将2D数组声明为参数,而第一个维度可能没有边界。 我想知道编译器如何跟踪第一个维度的长度,以及为什么它在后续维度上不一样?

由于无法编译以下代码:

int func(int array[][]) {
  return 0;
}

会产生

error: declaration of ‘array’ as multidimensional array must have bounds for all dimensions except the first

1 个答案:

答案 0 :(得分:2)

通常,编译器不会跟踪数组参数/参数的第一维。 (如果需要,这是对C标准要求的扩展,可能是提供边界检查的功能的一部分。)实际上,不可能将数组作为C中的参数传递,并且例程也无法声明一个数组作为参数。

当函数参数声明为数组时,根据C 2018 6.7.6.3 7,它会自动调整为指针:

  

将参数声明为“ 类型的数组”声明调整为“指向 type 的合格指针”,其中类型限定符(如果有)是指定的在数组类型派生的[]中……

按照C 2018 6.3.2.1 3:将数组作为函数参数给出时,它将自动转换为指向其第一个元素的指针

  

除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则表达式的类型为“ 的数组” type ”转换为类型为“指向 type 的指针”的表达式,该表达式指向数组对象的初始元素……

因此,数组永远不会作为参数传递,也不会作为参数接收。仅传递指针。

C实现从不需要数组的长度即可提供任何标准的C行为。例如,假设一个参数声明为int x[3][4]。它会自动调整为int (*x)[4]。然后,如果函数中的代码使用x[i][j],则C实现需要在内存中找到该元素。 i*4+j个元素超出x指向的位置。该实现需要第二维来进行计算,因为它必须增​​加i个子数组才能找到元素x[i][j]。由于它是按子数组递增的,因此需要知道子数组的大小。

但是,C实现不需要知道数组有多大。没有表达式会要求它使用数组的大小。因此,仅具有指向数组第一个元素的指针就足够了。