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

C語言左值右值深度解析:數組名與指針的內存訪問本質區別

     編輯:關於C語言

C語言左值右值深度解析:數組名與指針的內存訪問本質區別

左值:賦值號左側,代表**內存地址**(編譯期確定)。
右值**:賦值號右側,代表**地址中存儲的數據**(運行期讀取)。

符號雙重身份表

符號左值語境右值語境
int a地址 &a數值
int *p指針變量地址 &p指向的地址 p
*p目標地址 p目標數值
int arr[10]**非法**(常量地址)首元素地址 &arr[0]
"hello"非法首字符地址

關鍵差異:直接引用 vs 間接引用

  • 數組名:編譯器知曉基址與長度,arr[i] 直接計算 base + i*sizeof,**無運行期指針讀取**。
  • 指針:必須先讀取指針變量值(地址),再解引用,**多一次間接訪問**。

實測代碼驗證

char ga[] = "abcdefghijklmn";
char *gp = "abcdefghijklmn";

printf("ga  = %#x\n", ga);   // 數組名右值 → 首地址
printf("&ga = %#x\n", &ga);   // 數組地址 → 同值,類型不同
printf("gp  = %#x\n", gp);   // 指針右值 → 字面量地址
printf("&gp = %#x\n", &gp);   // 指針變量自身地址

void fa(char ca[10]) {  // 退化為 char *ca
    printf("&ca = %#x\n", &ca);  // 形參指針變量地址(棧上)
    printf("ca  = %#x\n", ca);   // 同實參首地址
    ++ca; // 合法:修改局部副本
}
void fp(char *pa) {
    printf("&pa = %#x\n", &pa);
    printf("pa  = %#x\n", pa);
    ++pa;
}

跨文件聲明陷阱

// file1.c
int a[10];
// file2.c
extern int *a;  // 錯誤!以指針方式訪問 → 先讀地址再解引用 → 崩潰
// 正確:extern int a[]; 或 extern int a[10];

總結

  • 數組名 = 地址常量(右值直接給地址,無左值)。
  • 指針 = 地址變量(有左值,右值給它存的地址)。
  • 函數參數 char a[] 實為 char *a,調用時傳數組名仍按地址傳遞。
  • 搞清左/右值、直接/間接引用,指針數組所有「反直覺」行為皆有章可循。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved