陣列名真的不是指標
阿新 • • 發佈:2019-01-03
前言:
事實告訴我們,二維陣列名不等於二級指標
那一維陣列呢?
對於一維陣列,用一級指標指向陣列名,用一級指標做引數傳遞一維陣列,似乎毫無問題。
void f(int *p);
int main(void)
{
int arr[2];
int *p = arr;
f(arr);
return 0;
}
那麼下面的例子呢?
1、sizeof 指標是指標的大小,sizeof 陣列名是整個陣列的大小
int *p;
int arr[4];
printf("sizeof(p) = %d \n", sizeof(p));
printf("sizeof(arr) = %d " , sizeof(arr));
Output:
sizeof(p) = 8
sizeof(arr) = 16
2、指標可以遞增操作,而陣列名不可以
int arr[4] = {1, 2, 3, 4};
int *p = arr;
printf("*(++p) = %d", *(++p)); // Output:*(++p) = 2
printf("*(++arr) = %d", *(++p)); // error
Output error:
error: lvalue required as increment operand
這裡出現了兩個問題:
- 陣列名不能遞增,那陣列名可能是常量指標啊
int *const arr
- 根據錯誤提示,陣列名是不能作為左值的,陣列名只能作為右值
陣列名也不是常量指標:
1、常量指標可以作為左值,而陣列名不可以:
int i = 1;
int arr[2];
int *const p = &i; // OK
arr = &i; // error
事實上,查閱資料可以發現:
- 陣列的型別是 type[SIZE] (二維陣列的型別是type(*)[SIZE])
- 常量指標的型別是 type* const
兩者並不是同一種資料型別,關於這一點:
我個人認為在C語言中,陣列也是一種資料型別,一種特殊的資料型別
我們知道,在向函式傳遞二維陣列的時候,我們使用了陣列指標,即int (*p)[n]
而陣列指標,我們可以理解為C語言為陣列創造的一種特殊的指標型別。
2、觀察下面例子,詳細內容可以參見 這裡
printf("%#x \n", a);
printf("%#x \n", &a);
printf("%#x \n", &a[0]);
printf("%#x \n", &a[0][0]);
Output:
0x9ffe40
0x9ffe40
0x9ffe40
0x9ffe40
我們可以發現,對於陣列名,處於不同型別下,取得的值(地址)都是一樣的
這個例子的意思是,陣列名和指標存在著隱式轉換。
這也是很多人把陣列名當作指標的原因,因為陣列名在大多數的情況下都會隱式轉換為指標,由於陣列名只能作為右值,所以指標也是一個右值的指標。
既然大多數情況下會隱式轉換為指標,那麼下面就是少數情況(不會轉換為指標):
- 對陣列名取地址的時候
- 用sizeof運算子運算的時候
- 用字串字面量初始化陣列的時候
總結:
在C語言中,陣列名確實和指標有著微妙的關係
但是陣列名並不是指標,由於它大部分情況下都表現為一個指標
所以很多地方都認為它是指標,事實上並不是,它只是很像指標而已
我個人認為陣列是C語言中一種特殊的資料型別,有著特定型別的指標