C語言中“陣列名”和“&陣列名”

ARM的程式設計師敲著詩歌的夢發表於2020-04-04

C語言中 陣列名&陣列名

== 實驗環境 ==
1. 編譯器:gcc 5.4.0
2. 作業系統:Ubuntu 16.04 x86_64

緣起

本以為此知識點我已熟練掌握,可是最近應用的時候還真給記混淆了。所以寫篇文章加深印象。

Show me the code

廢話少說,show me the code.

#include <stdio.h>

int main(void)
{
    int array[5] = {0};

    printf("1.          array = %p\n", array); 
    printf("2.         &array = %p\n", &array); 
    printf("3.      &array[0] = %p\n", &array[0]); 
    printf("4.      array + 1 = %p\n", array + 1);
    printf("5.  &array[0] + 1 = %p\n", &array[0] + 1);
    printf("6.     &array + 1 = %p\n", &array + 1);
    printf("7.  sizeof(array) = %lu\n", sizeof(array)); 

    return 0;
}

請你思考一分鐘,然後再看答案。

執行結果是:

這裡寫圖片描述

討論

在絕大多數關於陣列的表示式中,陣列名代表指標常量,這個指標指向陣列首個元素。從數值上講,陣列名錶示的值就是首個元素的地址。 從結果的第1行和第3行,第4行和第5行,都可以驗證這一點,即array的值就等於&array[0]的值。

剛才已經說過,陣列名代表指標常量,且這個指標指向陣列首個元素。當對這個指標進行加減的時候,以一個陣列元素為顆粒度。例子中的陣列元素為整型,所以陣列名加1時地址加4. 對比第4行和第1行,可以驗證。

但是,在以下2種語境中,陣列名並不是上面說的指標常量。
1. sizeof(陣列名)
2. &陣列名

對於1,sizeof(陣列名)返回整個陣列的長度,而不是指標常量的長度。 結果的第7行,返回20(=4*5),而不是返回8(因為地址寬度是64位,所以指標佔8位元組)。

對於2,對陣列名取地址所產生的值的型別是一個指向整個陣列的指標,而不是一個指向指標常量的指標。所以&array的型別是指向整個陣列的指標,而array是指向array[0]的指標,雖然在數值上相同(結果的第1行和第2行),但是在型別上不同。

正因為它們的型別不同,所以在加1或減1的時候,顆粒度不同。array以一個陣列元素為顆粒度,例子中的陣列元素為整數,所以array加1時地址加4(對比結果的1、4兩行);而&array以整個陣列為顆粒度,例子中的陣列為有5個元素的整型陣列,所以&array加1時,地址加20(對比結果的2、6兩行)。

總結

  1. 絕大多數情況下,陣列名代表指標常量,這個指標常量指向陣列首個元素。從數值上講,陣列名的值就是首個元素的地址。當對這個指標常量進行加減的時候,以一個陣列元素為顆粒度。

  2. sizeof(陣列名)&陣列名 這2種語境中,陣列名並不是上面說的指標常量。 sizeof(陣列名)返回整個陣列的長度,而不是指標常量的長度。&陣列名 的型別是一個指向整個陣列的指標,而不是一個指向指標常量的指標。

  3. 陣列名&陣列名雖然在數值上相同,但是在型別上不同——陣列名是指向首個元素的指標,&陣列名是指向整個陣列的指標。在指標加減整數的時候,前者以一個元素為顆粒度,後者以整個陣列為顆粒度。

參考資料
https://blog.csdn.net/wangkeyen/article/details/50650000

相關文章