这个函数调用和定义如何排列?

How does this function call and definition line up?

我刚刚在 C 中遇到这个函数 call/declaration 对,我有点困惑(我是这里的新手,但我没有在任何 material 我一直在用它来学习)。函数声明为 bool read_matrix(double a[][M], int n, int m),但它是由 read_matrix((double (*)[M]) a, n, m) 调用的。 (M 是由 #define 设置的整数。)这些参数如何相互对齐?就此而言,(*)[M] 是什么类型的对象?

感谢您解惑。

当一个函数参数像在这个函数声明中那样用数组类型声明时

bool read_matrix(double a[][M], int n, int m);

然后由编译器调整为指向元素类型的指针。

所以这个函数声明等同于声明

bool read_matrix(double ( *a )[M], int n, int m);

另一方面,表达式中使用的数组指示符(例如作为参数)被转换为指向其第一个元素的指针。

所以如果在函数的调用者中你有一个声明为

的数组
double a[N][M];

然后传给函数like

read_matrix( a, N, M );

它被转换为指向其第一个类型 int ( ^ )[M] 的指针。

至于你展示的通话中的演员表

read_matrix((double (*)[M]) a, n, m)

那么如果 a 是一个如上所示声明的数组,则强制转换是多余的。这种转换是隐式发生的。

除非它是 sizeof_Alignof 或一元 & 运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则类型 "N-element array of T" 的 表达式 将被转换 ("decay") 为类型 "pointer to T" 的表达式并且表达式的值将是数组的第一个元素。

当你传递一个数组表达式作为函数参数时,函数实际接收的是一个指针值:

void foo( T *a ) // equivalent to T a[] and T a[N]
{
  ...
}

int main( void )
{
  T arr[N];
  ...
  foo( arr );
  ...
}

作为 "convenience" C 允许您使用数组表示法作为函数参数声明,但请注意它将 "adjusted" 用作指针声明,因为参数 指针值,而不是数组 - T a[N]T a[] 将被解释为 T *a。请注意,这 只有 在函数参数声明中为真,而不是在常规变量声明中。

现在,只是为了好玩,将 T 替换为数组类型 double [M]。因此,arr 不再是 T 的 N 元素数组,而是 double:

的 M 元素数组的 N 元素数组
int main( void )
{
  double arr[N][M];
  ...
  foo( arr );
  ...
}

在对 foo 的调用中,表达式 arr "decays" 从类型 "N-element array of M-element arrays of double" 到 "pointer to M-element array of double" 或 double (*)[M]。所以我们的 foo 声明看起来像这样:

void foo( double (*a)[M] ) // equivalent to double a[][M] and double a[N][M]
{
  ...
}

这就是为什么这两个看似不同的声明是等价的——在函数参数声明的上下文中,double a[][M] 被解释为 double (*a)[M]。同样,这仅适用于函数参数声明,而不适用于常规变量声明。