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

C語言指針與字符串本質:左值、右值、數組名與指針的內存語義差異

     編輯:關於C語言

C語言指針與字符串本質:左值、右值、數組名與指針的內存語義差異

理解「左值(地址)」與「右值(值)」的區別,是掌握 C 指針、數組、字符串的鑰匙。

核心概念

  • 左值:出現在賦值號左側,代表內存地址(編譯期可知,運行期固定)。
  • 右值:出現在賦值號右側,代表存儲在該地址的數據(運行期讀取)。

各類符號的雙重身份

關鍵代碼驗證

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 my_array_func(char ca[10]) {
    printf("&ca = %#x\n", &ca);   // 形參退化為指針,&ca 是棧上指針變量地址
    printf("ca  = %#x\n", ca);    // 同實參首地址
    ++ca; // 合法:修改局部指針副本
}
void my_pointer_func(char *pa) {
    printf("&pa = %#x\n", &pa);   // 棧上指針變量地址
    printf("pa  = %#x\n", pa);    // 同實參地址
    ++pa; // 合法
}

數組名 ≠ 指針:直接引用 vs 間接引用

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

跨文件聲明陷阱

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

總結

  • 數組名是「地址常量」,右值語境下直接代表首地址。
  • 指針是「地址變量」,右值語境下代表它存儲的地址。
  • char *p = "str" 中,"str" 作右值提供地址賦給 p;p 自身有地址(左值)。
  • 函數參數 char a[] 實際退化為 char *a,但調用時傳遞數組名仍按地址傳遞。

搞清左值/右值、直接/間接引用,指針與數組的一切「怪異行為」皆有迹可循。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
符號作左值時作右值時
普通變量 a地址 &a數值
指針 p指針自身地址 &p指向的地址 p(即 *p 的地址)
解引用 *p目標地址 p目標數值
數組名 arr非法(數組名是常量指針)首元素地址 &arr[0]
字符串字面量 "hello"非法首字符地址