核心建議
- 理解陣列在記憶體中的連續佈局。
- 不要對指標用
sizeof 取得陣列長度(指標大小固定 4/8 bytes)。
- 顯式傳遞陣列長度參數,即使有初始化列表。
規則與違規/合規範例
1. 保證索引在合法範圍
// 違規:pos 為 signed,負數導致越界寫入
int insert(int pos, int val) { table[pos] = val; }
// 合規:用 size_t,負數自動轉大正數觸發檢查失敗
int insert(size_t pos, int val) {
if (pos >= TABLESIZE) return -1;
table[pos] = val; return 0;
}
2. 跨檔案陣列聲明一致性
// 違規:main.c 定義 char *a; insert.c 声明 extern char a[];
// 合規:共用頭檔 insert.h: extern char *a; 兩邊皆為指標
3. 變長陣列 (VLA) 長度檢查
// 違規:直接用參數建 VLA,可能耗盡棧
void func(size_t s) { int vla[s]; }
// 合規:限制上限
#define MAX_ARRAY 1024
void func(size_t s) {
if (s && s < MAX_ARRAY) { int vla[s]; ... }
else { /* error */ }
}
4. 複製目標空間足夠
void func(const int src[], size_t len) {
int dest[256];
if (len > 256) return; // 或截斷
memcpy(dest, src, len * sizeof(int));
}
5. 多維陣列型別相容
// 違規:int arr1[20][15]; int (*arr2)[10]; arr2=arr1; // 次維不匹配
// 合規:次維一致
int arr1[20][10]; int (*arr2)[10]; arr2 = arr1;
6. 迴圈不超出陣列尾端
// 違規:for (p=arr; p<=arr+N; p++) ... // 多跑一次
// 合規:for (p=arr; p
7. 不比較/相減不同陣列的指標
// 違規:if (p1 > p2) ... // p1,p2 指向不同陣列,UB
// 合規:只比較同一陣列內指標
8. 指標運算不超出陣列邊界
// 違規:int *p = &obj; p += 10; // obj 非陣列
// 合規:int arr[10]; int *p = arr; p += 5; // 在 arr 範圍內
9. 結構體非陣列不可用指標運算遍歷
// 違規:結構體欄位不保證連續
struct { short n1,n2,...n9; } s;
for (p=&s.n1; p<=&s.n9; p++) sum += *p; // 中間可能有 padding
// 合規:改用陣列
short arr[9] = {1..9};
for (p=arr; p
總結口訣
sizeof(指標) ≠ 陣列長度,長度必須顯式傳遞。
- 索引用
size_t,邊界檢查 && 連寫。
- 跨檔
extern 型別必須一致(指標對指標、陣列對陣列)。
- VLA 設上限,防棧溢位。
memcpy 目標緩衝區必須 ≥ 來源長度。
- 多維陣列次維必須匹配。
- 指標運算只在同一陣列內,結構體用陣列代替。