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

C語言指針進階:陣列指針與指針陣列的記憶體佈局解析

     編輯:關於C

經典面試題:int a[5] = {1,2,3,4,5}; int *p1 = (int*)(&a+1); int *p2 = (int*)((int)a+1); 輸出 p1[-1] 和 *p2 分別是多少?本文從記憶體佈局、指針運算、類型轉換三個維度徹底講透。

記憶體佈局圖解

假設 a 起始地址 0x100 (32位系統,int 4字節)
a[0] @0x100=1, a[1]@0x104=2, a[2]@0x108=3, a[3]@0x10C=4, a[4]@0x110=5
&a       : 類型 int(*)[5],值 0x100
&a + 1   : 類型 int(*)[5],值 0x100 + 5*4 = 0x114 (陣列尾後)
(int*)(&a+1) : 強轉為 int*,指向 0x114
p1[-1]   : *(p1 - 1) = *(0x114 - 4) = *0x110 = a[4] = 5  ✓

(int)a   : 將陣列首地址 0x100 視為整數
(int)a+1 : 0x101 (地址+1字節)
(int*)((int)a+1) : 強轉為 int*,指向 0x101
*p2      : 讀取 0x101 起始 4 字節組成的 int (小端序)
          內存: 0x100=01, 0x101=00, 0x102=00, 0x103=00 (a[0]=1)
          0x101=00, 0x102=00, 0x103=00, 0x104=02 (a[1]=2 的低位)
          組合: 0x02000000 = 33554432 (視具體機器碼而定)

實測輸出

p1[-1] = 5
*p2    = 33554432  (小端機器上,讀取 a[0] 低 3 字節 + a[1] 低 1 字節)

注意:*p2 屬於未定義行為 (違反嚴格別名規則、對齊要求),不同編譯器/優化等級結果可能不同,絕不可用於生產代碼。

核心知識點總結

表達式類型值(地址)解引用結果
&aint(*)[5]陣列首地址整個陣列 (不可解引用為 int)
&a+1int(*)[5]陣列尾後地址越界
(int*)(&a+1)int*陣列尾後地址p1[-1] 合法訪問最後元素
(int)aint (整數)首地址數值非指針不可解引用
(int*)((int)a+1)int*首地址+1字節**未定義行為** (對齊/別名違規)

避坑指南

  1. 陣列名 vs &陣列名:a 退化為 int* (首元素地址);&a 類型為 int(*)[5] (整個陣列地址),步長差異巨大。
  2. 指針運算單位:由指針**類型**決定,int* ±1 移動 4 字節;int(*)[5] ±1 移動 20 字節。
  3. 整數轉指針:(int*)integer 純粹重新解釋位址,編譯器不保護對齊、類型安全,**極度危險**。
  4. 負下標:p[-1] 等價 *(p-1),只要結果地址合法即可,常用於「指向陣列尾後的指針倒序訪問」。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved