C语言中的数组名的隐式转换
1.数组名的隐式转换规则
在C语言中数组名在绝大多数表达式场景中,会自动转换成指向数组首元素的指针
1.1触发条件
当数组名作为表达式使用时,除两种情况外,都会发生该隐式转换
1.2触发结果
数组名会转化为指向数组首元素的指针,指针的类型由数组元素的类型决定
例外
1.数组名作为sizeof的操作数
2.数组名作为&的操作数
为了便于加深其重要性的理解,我下面举几个例子
下面我用退化代替隐式转换
//这里以32位系统,int占4字节为前提
#include<stdio.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));
//结果为4,arr先与*结合,发生退化,对首元素地址解引用得到首元素,int型,所以结果是4
printf("%zu\n",sizeof(&arr + 1));
//结果为4,arr先与&结合,取出整个数组的地址,类型为数组指针int(*)[5],再加一还是数组指针,相当于跳过了一个含有五个int类型的数组,指针在32位系统下占4个byte
return 0;
}
我们再来看几个例子
#include<stdio.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;
}

浙公网安备 33010602011771号