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

C語言數組完全指南:一維/多維定義、初始化、常見操作、參數傳遞退化與經典錯誤

     編輯:關於C語言

為什麼需要數組?

  • 批量存儲**同類型**數據,連續內存,下標 O(1) 隨機訪問。
  • 建模現實實體:矩陣、圖像像素、查找表、環形緩衝區、狀態機表...

一維數組

定義與初始化

// 完全初始化
int a[5] = {1, 2, 3, 4, 5};

// 不完全初始化 — 剩餘元素**自動零初始化**
int b[5] = {1, 2, 3};     // {1,2,3,0,0}
int c[5] = {0};           // 全 0 (通用清零寫法)

// 省略長度 — 編譯器按初始化列表推導
int d[] = {10, 20, 30};   // 長度 3

// 未初始化 — 局部變量值不確定 (垃圾值),靜態/全局自動 0
int e[5];

核心操作模式

操作代碼片段關鍵點
遍歷for (int i=0; i下標 0~n-1,越界 UB
拷貝for (i=0; i**不可** dst = src (指針賦值)
查找for (i=0; i返回下標或 -1
插入 (有序)後移元素 → 放入 → 長度+1需預留空間,O(n)
刪除前移元素覆蓋 → 長度-1O(n)
反轉for (i=0,j=n-1; i原地 O(n)
排序qsort(arr, n, sizeof(int), cmp);庫函數,需比較函數
最大/最小max=arr[0]; for(i=1;imax) max=arr[i];單趟掃描

經典錯誤示範

int a[5] = {1,2,3,4,5};
int b[5];

// ❌ 錯誤 1: 整體賦值 (只有定義時允許)
b = a; // error: assignment to expression with array type

// ❌ 錯誤 2: 下標越界
a[5] = 100; // UB: 最大下標 4

// ❌ 錯誤 3: 定義後整體初始化
int c[5];
c = {1,2,3,4,5}; // error: 初始化列表只能用於定義

// ✅ 正確拷貝
for (int i=0; i<5; i++) b[i] = a[i];
// 或 memcpy(b, a, sizeof(a));

二維數組

定義與內存佈局

int a[3][4]; // 3 行 4 列,共 12 個 int,連續佈局
// 內存順序: a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] ... a[2][3]
// a[i][j] 偏移 = (i * 4 + j) * sizeof(int)

初始化

// 扁平列表 (按行優先)
int a[3][4] = {1,2,3,4, 5,6,7,8, 9,10,11,12};

// 分行列表 (推薦,可讀性強)
int b[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 部分初始化
int c[3][4] = {{1,2}, {3}}; // 剩餘自動 0

遍歷與常見操作

// 行優先遍歷 (緩存友好)
for (int i=0; i<3; i++)
    for (int j=0; j<4; j++)
        printf("%d ", a[i][j]);

// 求每行最大值
for (int i=0; i<3; i++) {
    int max = a[i][0];
    for (int j=1; j<4; j++)
        if (a[i][j] > max) max = a[i][j];
    printf("Row %d max = %d\n", i, max);
}

// 矩陣轉置 (方陣原地)
for (int i=0; i

多維數組本質

不存在真正的多維數組 — 內存是線性一維的。int a[3][4][5] 是**含 3 個元素的一維數組**,每個元素是 int[4][5] (即 4 行 5 列的二維數組)。

訪問 a[i][j][k] 等價 *(*(*(a+i)+j)+k),編譯器按行優先計算線性偏移。

數組作為函數參數 — 退化為指針

void func(int arr[10]) { }      // 等價 void func(int *arr)
void func(int arr[][4]) { }     // 二維:第一維退化,第二維保留 (需知列數計算偏移)
void func(int (*arr)[4]) { }    // 等價寫法:指向「含 4 個 int 的數組」的指針

// 內部 sizeof(arr) = 指針大小 (4/8),**無法獲取數組長度**
// 必須額外傳長度參數
void process(int *arr, size_t len);

避坑檢查清單

  1. ❌ **下標越界** — C 不檢查,導致靜默內存破壞、難以調試。用靜態分析、-fsanitize=address、邊界斷言。
  2. ❌ **變長數組 (VLA) int a[n]** — C99 特性,C11 可選,棧溢出風險,不可移植。**嵌入式/關鍵系統禁用**,用動態分配 malloc。
  3. ❌ **函數參數用 sizeof(arr) 計算長度** — 退化為指針,得 4/8。**額外傳 len**。
  4. ❌ **多維數組參數漏寫列數** — void f(int a[][]) 錯誤,必須 void f(int a[][COLS])。
  5. ❌ **字符數組當字符串忘留 '\0' 位置** — char s[5] = "hello"; 溢出 (需 6 字節)。
  6. ✅ **定義時初始化 ={0}** — 統一清零,防未初始化讀取。
  7. ✅ **遍歷用 size_t 或 int**,避免符號/無符號比較警告。
  8. ✅ **大數組靜態/全局/動態分配** — 避免棧溢出 (通常棧 1~8MB)。

現代 C++ 替代建議

  • std::array — 固定長度,值語義,可拷貝、.size()、不退化。
  • std::vector — 動態長度、自動內存管理、豐富算法支持。
  • std::span (C++20) — 非擁有視圖,替代指針+長度參數。

總結

數組是 C 語言最基礎的聚合類型:**連續內存、固定長度、下標訪問、參數退化指針**。掌握「定義初始化、遍歷拷貝查找、二維行優先佈局、參數必傳長度、杜絕越界/VLA」,配合 memcpy/qsort/memset 等庫函數,即能高效、安全地處理批量同類型數據。C++ 新項目優先選 std::vector/std::array 享受類型安全與 RAII。

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