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;
}