目錄
一、數組名的理解
a.數組名代表數組首元素的地址
b. 兩個例外
二、使用指針來訪問數組
三、一維數組傳參的本質
一、數組名的理解
a.數組名代表數組首元素的地址
????????我們在使用指針訪問數組的內容時,有這樣的代碼:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
這里我們使用?&arr[0] 的方式拿到了數組第一個元素的地址,但是其實數組名本來就是地址,而且
是數組首元素的地址,我們來做個測試。
?我們發現數組名和數組首元素的地址打印出的結果一模一樣,數組名就是數組首元素(第一個元素)的地址。
b. 兩個例外
????????sizeof(數組名),sizeof中單獨放數組名,這里的數組名表示整個數組,計算的是整個數組的大小,單位是字節。
非單獨數組名,此時為一個地址:
sizeof(arr)此時就是計算 arr[ ] 占用空間的大小 10 * 4 = 40 bit。
??????????&數組名,這里的數組名表示整個數組,取出的是整個數組的地址(整個數組的地址和數組元素元素的地址是有區別的)。
觀察發現,&arr[ 0 ] == arr =?&arr,那么他們有什么區別嗎?前二者都指的是數組首元素的地址,而后是指數組的地址,它們在數值上相同,但在意義上不同,前二者為 int* 類型,后者為 int * [ ] 類型。
&arr [ 0 ]? 與 arr,每 +1 ,只跳過4個字節,也就是一個元素大小,而 &arr + 1 每次跳過40個字節,這是一個 arr[ ] 的大小。
??????除此之外,任何地方使用數組名,數組名都表示首元素的地址。
二、使用指針來訪問數組
????????有了前面知識的支持,再結合數組的特點,我們就可以很方便的使用指針訪問數組了。
#include <stdio.h>
int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//輸?int* p = arr;for (i = 0; i < sz; i++){scanf("%d", p + i);//scanf("%d", arr+i);//也可以這樣寫}//輸出for (i = 0; i < sz; i++){printf("%d ", *(p + i));}return 0;
}
????????數組名arr是數組首元素的地址,可以賦值給p,其實數組名arr和p在這里是等價的。那我們可以使用arr[ i ]可以訪問數組的元素,那p[?i ]是否也可以訪問數組呢?
將第64行的 *(p+i) 改為 p[ i ] 同樣可以運行,同理 arr[ i ] 應該等價于 *(arr+i),數組元素的訪問在編譯器處理的時候,也是轉換成首元素的地址+偏移量求出元素的地址,然后解引用來訪問的。
三、一維數組傳參的本質
????????數組是可以傳遞給函數的,但是我們發現,不可以在函數的內部計算數組的元素個數,只能將數組的元素個數作為參數傳遞給數組,這是為什么呢?
發現,在函數體內無法正確算出數組的元素個數。
????????數組名是數組首元素的地址;那么在數組傳參的時候,傳遞的是數組名,也就是說本質上數組傳參傳遞的是數組首元素的地址。那么sz2中的 sizeof(arr) 其實就是 sizeof(int*) = 4,這也很好說明了為啥sz2的數值為1。
總結:一維數組傳參,形參的部分可以寫成數組的形式,也可以寫成指針的形式,但其本質還是傳遞了數組首元素地址。
?