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

C 指針進階:徹底搞懂 char (*p)[] 與 char p[] 的本質區別

     編輯:關於C語言

現象:編譯警告「不兼容的指針類型賦值」

char (*p)[10];
char a[10];
p = a;  // 警告:assignment from incompatible pointer type

為什麼 p = &a 正確,而 p = a 報警?

核心概念辨析

1. 數組名 a 的雙重身份

  • 在大多數表達式中:a 退化為指向首元素的指針,類型為 char *,值為 &a[0]。
  • 作為 sizeof、& 操作元時:a 代表整個數組對象,類型為 char [10](或 char (*)[10] 經 & 取址後)。

2. &a vs a(退化後)

表達式類型值(地址數值)語義
a(退化)char *0x7fff...首元素地址
&achar (*)[10]0x7fff...(同值)整個數組地址
&a[0]char *0x7fff...(同值)首元素地址

關鍵點:數值相同,**類型不同**。指針賦值需類型匹配(或兼容),char (*)[10] 不能直接接收 char *。

3. char (*p)[10] 是什麼?

  • 「指向含 10 個 char 的數組的指針」。
  • p+1 增加 sizeof(char[10]) = 10 字節,跳到下一個同樣大小的數組。
  • 解引用 *p 得到類型 char [10](退化為 char * 可訪問元素)。

4. char p[] / char *p 是什麼?

  • char p[]:定義一個數組,p 是數組名(非修飾的左值,不可賦值/自增)。
  • char *p:定義一個指向 char 的指針,可指向單字符或字符串首元素。

正確用法示範

char (*p)[10];
char a[10];
strcpy(a, "hello");  // 初始化

p = &a;  // 正確:類型匹配,均為 char (*)[10]

// 訪問元素
printf("p = %s\n", *p);        // *p 退化為 char*,可作 %s
printf("2nd char = %c\n", (*p)[1]);  // 顯式解引用後下標

易混淆對比:指向數組的指針 vs 指針數組

宣告名稱含義sizeof(p) (32位)
char (*p)[10]指向數組的指針指向一個 10 元素數組4(指針大小)
char *p[10]指針數組含 10 個 char* 的數組40(10×4)
char **p指向指針的指針指向 char* 的指針4

常見誤區澄清

  1. 「數組名是常量指針」錯誤:標準說法是「數組對象是不可修改的左值」。它是左值(可取址),但不支援賦值/自增操作。非 const 修飾,不可稱為「常量」。
  2. &a 和 a 內容相同?:它們無「內容」概念(非對象),僅有「值」(地址數值)。值相等,類型不同:char (*)[10] vs char *。
  3. 為何 p = a 能跑通?:編譯器僅警告,因底層地址數值相同,運行時「碰巧」能訪問。但類型系統已失效,p+1 會跳 10 字節而非 1 字節,導致邏輯錯誤。

總結記憶口訣

  • char (*p)[N]:**括號優先**,p 先結合 * → 指針 → 指向大小 N 的數組。
  • char *p[N]:**下標優先**,p 先結合 [N] → 數組 → 元素是 char*。
  • 數組名 a:平時是「首元素指針」(char*),見 &/sizeof 變「整個數組」(char[N])。
  • 賦值給 char (*p)[N] 必須用 &a,類型才對齊。

掌握類型語義而非僅記語法,才能在複雜指針操作中游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved