为何f(int i[])是合法的声明,而f(int i[][])是不合法的声明

为什么f(int i[])是合法的声明,而f(int i[][])是不合法的声明?
数组作为参数传递给函数的时候,会退化成一个指针,这个我可以理解没有问题。
但是如果我声明了一个函数形如f(int i[][]),那么编译器会报错。为什么二维数组不能退化成一个指针呢?
------解决思路----------------------
因为规定。
换个语言,可能这么写就是合法的。
------解决思路----------------------
我试了一下,带上下标可以运行:

#include <iostream>
using namespace std;
void f(int a[][2]){
cout<<"此函数的形参是二维数组"<<endl;
}
void main(){
int x[2][2]={1,2,3,4};
f(x);
}

------解决思路----------------------
函数传递二维数组是一定要指定列的,原因是计算机的内存排列计数方式不是矩阵,而是低位 - >高位这么一长条,这里不方便给你画图,你可以自己画一下,如果你传递了i[][],计算机根本不知道行和列,新一行的起点也就不得而知,而只要知道列数,比如4,那我每一行的地址就是i+4,至于多少行并不重要,偏移量必不可少。

多维数组同理。
------解决思路----------------------
“二维数组”是不存在的, 只有数组的数组.


------解决思路----------------------
引用:
“二维数组”是不存在的, 只有数组的数组.


引用
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation.


举例子:

void f (int []); //void f(int*)
void g(int [][4]); // void f(int (*)[4])
void k(int [][5][6]); //void k(int (*)[5][6])

------解决思路----------------------
传递参数,其实就是在做赋值运算

比如 void fun(int a){}
调用这个函数:fun(2);
其实也就是做了这件事:int a = 2;

所以,一维数组时,int [] 和 int * 等效,因此传递一维数组为参数时,实际上就是写了:int *a = tabOneDim;  这显然是可以的
而如果是二维数组而你直接用int [][]的话,而int [][]和int **等效,因此,你就是在写:int **a = tabTwoDim; 这是不可以的

你可以在主函数里先定义出一个二维数组,然后试着把这个数组名给一个指针的指针赋值,编译器会报错


为什么会报错

因为c++编译器规定,多维数组每个元素的长度必须是已知的   这就类似于你不能定义一个这样的数组: int a[n];
数组长度必须是常量
------解决思路----------------------
问题在于,指针和数组是不完全等同的。
用指针的指针,或者楼上的数组的数组类描述更恰当。