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

C 这个函数调用和定义是如何排列的?,c,pointers,multidimensional-array,implicit-conversion,function-declaration,C,Pointers,Multidimensional Array,Implicit Conversion,Function Declaration,我刚刚在C中遇到了这个函数调用/声明对,我有点困惑(我在这里是一个新手,但我在学习的任何材料中都没有看到这个问题)。函数声明以bool read_matrix(double a[][M],int n,int M)形式给出,但它由read_matrix((double(*)[M])a,n,M)调用。。(M是由#define设置的整数)这些参数如何相互对齐?就这一点而言,(*)[M]是什么类型的对象 感谢您消除了混淆。当函数参数使用类似于此函数声明中的数组类型声明时 bool read_matrix

我刚刚在C中遇到了这个函数调用/声明对,我有点困惑(我在这里是一个新手,但我在学习的任何材料中都没有看到这个问题)。函数声明以
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);
然后编译器将其调整为指向元素类型的指针

所以这个函数声明与声明是等价的

bool read_matrix(double a[][M], int n, int m);
bool read_matrix(double ( *a )[M], int n, int m);
另一方面,表达式中用作参数的数组指示符被转换为指向其第一个元素的指针

因此,如果在函数的调用方中有一个声明为

double a[N][M];
然后传递给函数,如

read_matrix( a, N, M );
它被转换为指向其类型为
int(^)[M]
的第一个元素的指针

至于你在电话里的角色

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

如果
a
是如上所示声明的数组,则强制转换是冗余的。此转换是隐式进行的。

除非它是
sizeof
\u Alignof
或一元
&
运算符的操作数,或者是用于初始化声明中字符数组的字符串文字,否则将转换类型为“T的N元素数组”的表达式(“Decage”)指向类型为“指向
T
”的表达式,表达式的值将是数组第一个元素的地址

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

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

int main( void )
{
  T arr[N];
  ...
  foo( arr );
  ...
}
为了“方便”,C允许您使用数组表示法声明函数参数,但请注意,它将被“调整”为指针声明,因为参数是指针值,而不是数组-
TA[N]
TA[]
将被解释为
T*a
。请注意,这仅在函数参数声明中是正确的,而不是在正则变量声明中

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

int main( void )
{
  double arr[N][M];
  ...
  foo( arr );
  ...
}
在对
foo
的调用中,表达式
arr
从类型“double的M元素数组的N元素数组”衰减为“指向double的M元素数组的指针”,或
double(*)[M]
。因此,我们对
foo
的声明如下所示:

void foo( double (*a)[M] ) // equivalent to double a[][M] and double a[N][M]
{
  ...
}
这就是为什么两个看似不同的声明是等价的——在函数参数声明的上下文中,
double a[][M]
被解释为
double(*a)[M]
。同样,这仅适用于函数参数声明,而不是正则变量声明

(*)[M]
是一个数组,因为当传递给函数时,像
a[N][M]
这样的数组会衰减为指向像
(*ptr)[M]
这样的数组的指针