1. 程式人生 > >陣列名真的不是指標

陣列名真的不是指標

前言:

事實告訴我們,二維陣列名不等於二級指標

那一維陣列呢?

對於一維陣列,用一級指標指向陣列名,用一級指標做引數傳遞一維陣列,似乎毫無問題。

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

這裡出現了兩個問題:

  1. 陣列名不能遞增,那陣列名可能是常量指標啊 int *const arr
  2. 根據錯誤提示,陣列名是不能作為左值的,陣列名只能作為右值

陣列名也不是常量指標:

1、常量指標可以作為左值,而陣列名不可以:

int i = 1;
int arr[2];
int *const p = &i;  // OK
arr = &i;   // error

事實上,查閱資料可以發現:

  1. 陣列的型別是 type[SIZE] (二維陣列的型別是type(*)[SIZE])
  2. 常量指標的型別是 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

我們可以發現,對於陣列名,處於不同型別下,取得的值(地址)都是一樣的
這個例子的意思是,陣列名和指標存在著隱式轉換
這也是很多人把陣列名當作指標的原因,因為陣列名在大多數的情況下都會隱式轉換為指標,由於陣列名只能作為右值,所以指標也是一個右值的指標。

既然大多數情況下會隱式轉換為指標,那麼下面就是少數情況(不會轉換為指標):

  1. 對陣列名取地址的時候
  2. 用sizeof運算子運算的時候
  3. 用字串字面量初始化陣列的時候

總結:

在C語言中,陣列名確實和指標有著微妙的關係
但是陣列名並不是指標,由於它大部分情況下都表現為一個指標
所以很多地方都認為它是指標,事實上並不是,它只是很像指標而已
我個人認為陣列是C語言中一種特殊的資料型別,有著特定型別的指標