首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言陣列取址深度解析:a、&a[0]、&a 的類型與指標運算差異

     編輯:關於C語言

核心結論先行

表達式類型值 (位址)+1 後位址變化
aint * (指向首元素)陣列起始位址+ sizeof(int) (指向 a[1])
&a[0]int *陣列起始位址+ sizeof(int)
&aint (*)[4] (指向整個陣列)陣列起始位址+ sizeof(int[4]) (跨越整個陣列)

為什麼 &a 是「指向陣列的指標」?

陣列名 a 在大多數表達式中「退化」為指向首元素的指標 (int *),但它不是指標變數 (不可修改、無儲存空間)。對一個「非指標」實體取址 (&a),編譯器視其為「以整個陣列為單一元素」的聚合體,產生指向該聚合體的指標,類型為 int (*)[N]。

類比理解:層級遞增


int i;           // 0 階實體 (單一值)
int *p = &i;     // 1 階指標 (指向 0 階)
int **pp = &p;   // 2 階指標 (指向 1 階)
int ***ppp = &pp;// 3 階指標 ...

int a[4];        // 可視為「4 個 int 的聚合體」= 1 階聚合
int (*pa)[4] = &a; // 指向該聚合體 = 2 階

實證程式碼


#include 
int main() {
    int a[4] = {1,2,3,4};
    printf("a        = %p\n", (void*)a);
    printf("a+1      = %p  (diff %ld)\n", (void*)(a+1), (char*)(a+1)-(char*)a);
    printf("&a[0]    = %p\n", (void*)&a[0]);
    printf("&a[0]+1  = %p  (diff %ld)\n", (void*)(&a[0]+1), (char*)(&a[0]+1)-(char*)a);
    printf("&a       = %p\n", (void*)&a);
    printf("&a+1     = %p  (diff %ld)\n", (void*)(&a+1), (char*)(&a+1)-(char*)a);
    return 0;
}

典型輸出 (64-bit 系統)

a        = 0x7ffd12345670
a+1      = 0x7ffd12345674  (diff 4)
&a[0]    = 0x7ffd12345670
&a[0]+1  = 0x7ffd12345674  (diff 4)
&a       = 0x7ffd12345670
&a+1     = 0x7ffd12345680  (diff 16)  ← 關鍵:跨越整個陣列 4*4=16 bytes

實務應用場景

  1. 函數參數傳遞整個陣列:
    
    void process_matrix(int (*matrix)[4], int rows);  // 保留列數資訊
    int a[3][4];
    process_matrix(a, 3);  // a 類型自動轉為 int (*)[4]
    
  2. sizeof 運算元:sizeof(a) 給出整個陣列大小 (16),而非指標大小。
  3. 字串字面值:char *p = "abc"; 中 "abc" 類型為 char[4],&"abc" 為 char (*)[4]。

常見誤區

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
誤區正確理解
a 是指標a 是陣列,僅在值語境「退化」為指標;&a 類型不同證明之
&a 和 &a[0] 完全相同位址值相同,但類型不同,指標運算行為截然不同
強制轉型後無差別(void*)a == (void*)&a 只比較位址值,掩蓋類型語義差異