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

C/C++ 陣列與指標深度解析:相似卻不相同的關鍵差異

     編輯:關於C語言

核心觀念:陣列 ≠ 指標

雖然許多場合可互換(如 a[i] ≡ *(a+i)),但本質完全不同:

特性陣列指標
儲存位置靜態區(全域)或堆疊(區域)指向任意記憶體(堆疊、堆、靜態、記憶體映射)
位址/容量生命週期內固定不變可隨時修改指向
內容修改可修改元素可修改指向內容(若非指向常數)
sizeof整個陣列位元組數指標變數本身大小(4/8 位元組)
賦值/比較不可直接整體賦值/比較可直接賦值/比較位址

1. 內容修改:常數字串陷阱

char a[] = "hello";  // 陣列在堆疊,內容可改
a[0] = 'X';          // OK

char *p = "world";   // p 指向唯讀資料段(常數字串)
p[0] = 'X';          // 編譯通過,執行期崩潰(Segmentation Fault)

規則:字串常值型別為 const char[],指向其的指標應宣告為 const char*。

2. 複製與比較:陣列名非左值

char a[] = "hello";
char b[10];

// 錯誤:b = a;        // 陣列名非可修改左值
// 錯誤:if (b == a)   // 比較的是位址,非內容

strcpy(b, a);          // 正確複製
if (strcmp(b, a) == 0) // 正確比較

// 指標操作
char *p = malloc(strlen(a)+1);
strcpy(p, a);          // 複製內容
if (strcmp(p, a) == 0) // 比較內容
free(p);

3. sizeof 運算元差異

char a[] = "hello world"; // 含 '\0' 共 12 位元組
char *p = a;

printf("%zu\n", sizeof(a)); // 12
printf("%zu\n", sizeof(p)); // 4 (32-bit) 或 8 (64-bit)

// 函數參數傳遞:陣列退化為指標
void Func(char a[100]) {
    printf("%zu\n", sizeof(a)); // 4/8,非 100!
}

鐵律:陣列作為函數參數時,自動退化為同類型指標,失去長度資訊。解決:傳遞長度參數、使用結構體封裝、或 C++ 使用 std::array/std::vector。

4. 字串字面值、陣列、指標三者關係圖解

#define CONST_STR "const str"  // 預處理器直接替換

// 1. 陣列:擁有獨立記憶體,內容可改
char arr1[100] = CONST_STR;   // 複製到陣列
char arr2[100] = "literal";   // 複製到陣列

// 2. 指向常數字串:不可修改內容
const char *p1 = CONST_STR;   // 指向唯讀區
const char *p2 = "literal";   // 同上

// 3. 指向動態記憶體:可修改內容
char *p3 = malloc(100);
strcpy(p3, CONST_STR);        // 複製內容,可修改 p3[0] = 'X';

// 4. 常數指標:指標本身不可改
char *const p4 = arr1;        // p4 永遠指向 arr1,但可改內容

5. 實戰測試程式碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define CONST_STR "const str"

void test_array_strcpy_string() {
    char a[100];
    strcpy(a, "literal");
    a[0] = 'A'; // OK
    printf("array strcpy string: %s\n", a);
}

void test_pointer_string() {
    char *p = "literal"; // 指向常數
    // p[0] = 'A'; // Crash!
    printf("pointer string: %s\n", p);
}

void test_pointer_strcpy_string() {
    char *p = malloc(100);
    strcpy(p, "literal");
    p[0] = 'A'; // OK
    printf("pointer strcpy string: %s\n", p);
    free(p);
}

int main() {
    test_array_strcpy_string();
    test_pointer_string();
    test_pointer_strcpy_string();
    return 0;
}

總結:避坑指南

  1. 字串常值永遠加 const:const char *p = "...",編譯器會攔截修改嘗試。
  2. 需要修改字串內容:用陣列 char a[] = "..." 或 malloc+strcpy。
  3. sizeof 只能用於陣列定義可見的作用域;跨函數必須額外傳長度。
  4. 陣列名不可賦值;複製用 strcpy/memcpy,比較用 strcmp/memcmp。
  5. 指標靈活但危險:永遠初始化、檢查 NULL、明確擁有權(誰 free)。

深刻理解陣列與指標的記憶體模型差異,是寫出高效、無 Bug C/C++ 程式碼的基石。

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