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

C語言數組指針函數錯誤修正:宏定義衝突、局部數組返回、邊界越界

     編輯:C 語言問答

原代碼四大錯誤

#define N 2
int c[N] = {1, 2}, *pb;   // ① 初始化列表 2 個元素,但下面 scanf 讀 N 個,邏輯矛盾
for (int i = 0; i < N; i++)
    scanf("%d", &c[i]);   // ② 覆蓋初始值,但提示「輸入一個數組」語意不清

int *f(int *a) {
    int b[N];             // ③ 局部數組棧上分配
    for (int i = 0; i < N; i++)
        if (*(a+i) % 2 != 0)
            b[i] = *(a+i);  // ④ 未賦值元素留下垃圾值
    return &b[0];         // ❌ 返回局部數組地址 → 未定義行為 (棧幀銷毀)
}

修正版:動態分配 + 明確語義

#include 
#include 

int *filter_odd(const int *src, size_t n, size_t *out_len) {
    // 先計算奇數個數
    size_t cnt = 0;
    for (size_t i = 0; i < n; i++)
        if (src[i] % 2 != 0) cnt++;

    int *dst = malloc(cnt * sizeof(int));
    if (!dst) return NULL;

    size_t j = 0;
    for (size_t i = 0; i < n; i++)
        if (src[i] % 2 != 0)
            dst[j++] = src[i];

    *out_len = cnt;
    return dst;   // 堆內存,調用者負責 free
}

int main(void) {
    size_t N;
    printf("請輸入數組長度: ");
    if (scanf("%zu", &N) != 1 || N == 0) return 1;

    int *arr = malloc(N * sizeof(int));
    if (!arr) return 1;
    printf("請輸入 %zu 個整數 (空格分隔): ", N);
    for (size_t i = 0; i < N; i++)
        if (scanf("%d", &arr[i]) != 1) { free(arr); return 1; }

    size_t out_len;
    int *odd = filter_odd(arr, N, &out_len);
    free(arr);  // 原數組釋放

    if (!odd) { puts("內存不足"); return 1; }

    printf("奇數元素: ");
    for (size_t i = 0; i < out_len; i++)
        printf("%d ", odd[i]);
    putchar('\n');

    free(odd);  // 釋放結果數組
    return 0;
}

錯誤對照修正表

原錯誤後果修正方案
#define N 2 固定長度無法處理任意長度輸入運行時讀取長度,動態分配
局部數組 b[N] 返回地址函數返回後棧內存無效,訪問崩潰/垃圾值用 malloc 分配堆內存,或輸出參數填充調用者提供的緩衝區
未初始化 b[i] (偶數情況)結果數組含垃圾值只存入奇數,或預先 memset,或用動態數組精確大小
宏 N 與變量名衝突風險預處理器全局替換,易誤傷宏名全大寫加前綴 ARR_MAX_LEN,或用 const size_t / enum

進階模式:調用者分配緩衝區 (零拷貝風格)

// 返回實際寫入個數,緩衝區由調用者提供
size_t filter_odd_inplace(const int *src, size_t n, int *dst, size_t dst_cap) {
    size_t j = 0;
    for (size_t i = 0; i < n && j < dst_cap; i++)
        if (src[i] % 2 != 0)
            dst[j++] = src[i];
    return j;
}

掌握「誰分配誰釋放」、「避免返回棧地址」、「動態數組三部曲 (malloc/使用/free)」是 C 語言內存管理鐵律。

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