这个函数调用和定义如何排列?
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]
。同样,这仅适用于函数参数声明,而不适用于常规变量声明。
我刚刚在 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
:
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]
。同样,这仅适用于函数参数声明,而不适用于常规变量声明。