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

C 語言指標完整教學:從記憶體位址到進階應用

     編輯:關於C語言

前言

指標是 C 語言的靈魂,亦是初學者最大的挑戰。本文從記憶體位址概念切入,系統講解指標變數定義、間接存取、函數傳址呼叫、指標與陣列/字串關係、常見錯誤與練習,並補充邏輯/線性/物理位址轉換背景知識,助你建立扎實的指標心智模型。

一、記憶體位址與指標基礎

1.1 位址概念

位址是系統 RAM 中特定位置的編碼,通常以十六進位表示(如 `0x7fff5fbff81c`)。程式透過位址定位資料。在 80386 保護模式下,分為:

  • 邏輯位址:相對於當前程序資料段的偏移量(C 指標讀取到的值)。
  • 線性位址:經分段機制轉換後的位址。
  • 物理位址:經分頁機制(MMU)映射後送上記憶體匯流排的實際位址。

位址轉換關係圖

1.2 指標變數定義與基本操作

int a = 10;
int *p = &a;     /* p 儲存 a 的位址 */
*p = 20;         /* 透過 p 修改 a 的值,a 變為 20 */
printf("%p\n", p); /* 印出位址 */
printf("%d\n", *p); /* 印出 20 */
  • int *p; 中的 `*` 僅為宣告標記,非解參考運算。
  • 指標只能儲存位址,不可直接指定整數(如 `p = 200;` 錯誤)。
  • 未初始化的指標(野指標)不可解參考,否則未定義行為。

1.3 函數傳址修改外部變數

void change(int *n) { *n = 20; }
int a = 10;
change(&a); /* a 變為 20 */

二、指標與陣列

2.1 陣列名退化為指標

陣列名在運算式中(除 `sizeof`、`&` 外)退化為首元素位址。

int ages[5] = {10, 11, 19, 78, 67};
int *p = ages; /* 等價於 &ages[0] */
printf("%d\n", p[2]);   /* 19 */
printf("%d\n", *(p+2)); /* 19,指標算術:p+2 位址增加 2*sizeof(int) */

2.2 函數參數傳遞陣列

void change(int *array) { /* 或 int array[] */
    printf("%d\n", array[2]);
}
change(ages); /* 實際傳遞首元素位址 */

注意:函數內 `sizeof(array)` 回傳指標大小(8 bytes on 64-bit),非陣列總大小。

2.4 指標算術與類型

指標 `+1` 實際位址增加量 = `sizeof(指標指向類型)`。

  • `int *`:+4 bytes
  • `char *`:+1 byte
  • `double *`:+8 bytes

三、指標與字串

3.1 兩種定義方式差異

方式範例儲存區可修改內容適用場合
字元陣列`char name[] = "itcast";`堆疊是需頻繁修改字串
字元指標`char *name = "itcast";`常數區(唯讀)否(嘗試修改導致崩潰)唯讀、高頻使用字串
char name[] = "it"; name[0] = 'T'; /* OK */
char *name2 = "it"; *name2 = 'T'; /* Crash! */
char *name3 = "it"; printf("%p %p\n", name2, name3); /* 可能相同,編譯器優化合併常數 */

3.2 字串陣列與二維陣列

/* 指標陣列 */
char *names[5] = {"jack", "rose", "jake"};
/* 二維字元陣列 */
char names2[2][10] = {"jack", "rose"};

四、常見錯誤與練習

4.1 指標宣告陷阱

int *p, p1; /* p 是指標,p1 是 int,非雙指標 */
int *p, *p1; /* 正確:兩個指標 */

4.2 交換函數正確寫法

/* 錯誤:僅交換區域指標指向 */
void swap_wrong(int *v1, int *v2) { int *t = v1; v1 = v2; v2 = t; }

/* 正確:交換指向的值 */
void swap_correct(int *v1, int *v2) { int t = *v1; *v1 = *v2; *v2 = t; }

4.3 練習:字元指標與位元操作

char c = 1;        /* 0000 0001 */
char *p = &c;
printf("%d\n", *p); /* 1 */

void test() {
    char *cp; int *ap; long *bp;
    printf("%zu %zu %zu\n", sizeof(cp), sizeof(ap), sizeof(bp)); /* 64-bit 皆為 8 */
}

五、總結

指標本質是位址,核心操作是 `&`(取址)與 `*`(解參考)。掌握指標與陣列/字串的關係、指標算術規則、const 修飾位置(`const int *` vs `int * const`)、以及避免野指標與類型不匹配,即可駕馭 C 語言最強大也最危險的特性。

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