在C语言中数组名在绝大多数表达式场景中会自动转换成指向数组首元素的指针1.1触发条件当数组名作为表达式使用时除两种情况外都会发生该隐式转换1.2触发结果数组名会转化为指向数组首元素的指针指针的类型由数组元素的类型决定例外1.数组名作为sizeof的操作数2.数组名作为的操作数为了便于加深其重要性的理解我下面举几个例子下面我用退化代替隐式转换//这里以32位系统int占4字节为前提 #includestdio.h int main() { int arr[5] { 0 }; printf(%zu\n,sizeof(arr)); //此时输出的结果为20数组名作为sizeof的操作数未发生退化视为整个数组 printf(%zu\n,sizeof(arr 1)); //此时输出的结果为4数组名先与结合发生隐式转换视为数组首元素的指针int*再加一为指向arr[1]的指针又是32位系统所以是4 printf(%zu\n,sizeof(*arr)); //结果为4arr先与*结合发生退化对首元素地址解引用得到首元素int型所以结果是4 printf(%zu\n,sizeof(arr 1)); //结果为4arr先与结合取出整个数组的地址类型为数组指针int(*)[5],再加一还是数组指针相当于跳过了一个含有五个int类型的数组指针在32位系统下占4个byte return 0; } 我们再来看几个例子 #includestdio.h int main() { int arr[3][5] { 0 }; printf(%zu\n,sizeof(arr)); //未发生退化是整个二位数组类型int[3][5],结果为60 printf(%zu\n,sizeof(arr[0][0])); //表示第一个二维数组首元素int类型所以结果为4 printf(%zu\n,sizeof(arr[0])); //可视为*(arr 0),发生退化当然不这么看也可以可以理解为下标引用结合后直接是二维数组的首个一维数组的数组名但这个假想的数组其实没名字也就是第0行 //arr代表二维数组的第一个元素也就是所谓的第一行的数组int[5]的指针这和下标引用操作符有关再0不变解引用后就变为了第一行的数组所以结果为20 //本质上就是表示二维数组的第一个元素也就是第一行所以结果为20 printf(%zu\n,sizeof(arr[0] 1)); //参与表达式运算arr[0]可以看作计算出了int[5],(不过这个子数组没名字我就写成这种形式了上面的例子也是一个道理)参与计算发生衰退变为指向首元素的指针int* //加一相当于指向了第二个元素下标是1的指针所以结果为4 //第一行参与运算退化变为指向第一行的数组指针加一变为指向第二行指针所以结果为4 printf(%zu\n,sizeof(arr 1)); //数组名参与表达式运算发生退化变为指向首元素的指针int(*)[5]就是第一行下标为零加一是第二行但是是指针所以结果为4 printf(%zu\n,sizeof(*(arr 1))); //对第二行的数组指针解引用得到第二行结果为20 printf(%zu\n,sizeof(arr[0] 1)); //取出第一行的地址是一个数组指针加一变为指向第二行的数组指针结果为4 printf(%zu\n,sizeof(*(arr[0] 1))); //对指向第二行的数组指针解引用得到第二行结果为20 printf(%zu\n,sizeof(*arr)); //数组名与*结合退化为首元素的指针也就是指向第一行的数组指针解引用得到第一行结果为20 printf(%zu\n,sizeof(arr[4])); //虽然越界了但sizeof只看类型不进行实际的运行所以结果为20 return 0; }