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

C語言斐波那契數列生成邏輯詳解:數組下標陷阱與循環邊界分析

     編輯:C 語言問答

原始代碼還原與問題定位

#include <stdio.h>
void main() {
    int i;
    int f[5] = {1, 1};      // 只有 f[0], f[1] 顯式初始化為 1,其餘 f[2]~f[4] 隱式初始化為 0
    for (i = 2; i <= 5; i++)  // 錯誤 1: 循環條件 i<=5 導致訪問 f[5] 越界 (有效下標 0~4)
        f[i] = f[i-2] + f[i-1]; // 錯誤 2: f[5] 寫入越界,破壞棧幀
    for (i = 0; i <= 5; i++) {  // 錯誤 3: 同樣越界讀取 f[5]
        if (i % 5 == 0) printf("\n");
        printf("%12d", f[i]);
    }
    printf("\n");
}

核心邏輯錯誤深度剖析

1. 數組大小與下標邊界不匹配

  • int f[5] 分配 5 個 int,合法下標 0, 1, 2, 3, 4。
  • 第一個循環 i <= 5 會執行 i = 2,3,4,5 四次,f[5] 寫入越界 (緩衝區溢出),行為未定義 (UB)。
  • 第二個循環 i <= 5 同樣讀取 f[5] 越界。

2. 斐波那契邏輯正確性 (修正邊界後)

若修正為 int f[6] 或循環 i < 5 (配合 f[5]):

f[0] = 1
f[1] = 1
i=2: f[2] = f[0] + f[1] = 1 + 1 = 2
i=3: f[3] = f[1] + f[2] = 1 + 2 = 3
i=4: f[4] = f[2] + f[3] = 2 + 3 = 5
i=5: f[5] = f[3] + f[4] = 3 + 5 = 8  // 需 f[6] 容納

輸出前 6 項 (下標 0~5):1 1 2 3 5 8。

3. 格式化輸出邏輯

for (i = 0; i <= 5; i++) {
    if (i % 5 == 0) printf("\n");  // i=0,5 時換行
    printf("%12d", f[i]);          // 每個數佔 12 寬度右對齊
}

輸出樣式:

           1           1           2           3           5
           8

標準修正版代碼

#include <stdio.h>

int main(void) {
    const int N = 10;              // 計算前 N 項
    int f[N];
    f[0] = 1;
    f[1] = 1;
    for (int i = 2; i < N; ++i)  // 正確邊界: i < N
        f[i] = f[i-2] + f[i-1];
    
    for (int i = 0; i < N; ++i) {
        if (i % 5 == 0) putchar('\n');  // 每 5 個換行
        printf("%12d", f[i]);
    }
    putchar('\n');
    return 0;
}

關鍵知識點總結

知識點錯誤認知正確理解
數組下標以為 f[5] 是第 5 個元素f[5] 是第 6 個元素,f[0] 是第 1 個,f[n-1] 是第 n 個
循環邊界習慣寫 i<=nC 語言慣用半開區間 [0, n),循環條件 i < n
越界後果以為會報錯C 不做邊界檢查,越界屬 UB,可能沉默破壞數據/棧/返回地址,極難調試
隱式初始化以為未初始化是隨機值部分初始化的數組,剩餘元素保證為 0 (靜態/全局/局部靜態均如此)
main 返回類型void main()標準要求 int main(void) 或 int main(int argc, char *argv[])

進階擴展:大數斐波那契

第 93 項超過 unsigned long long (2^64-1)。需實現高精度加法 (數組/鏈表存十進制位) 或使用 GMP 庫。

// 高精度斐波那契框架 (十進制位數組,低位在前)
#define MAX_DIGITS 1000
void add_big(int *res, const int *a, const int *b, int len) {
    int carry = 0;
    for (int i = 0; i < len; ++i) {
        int sum = a[i] + b[i] + carry;
        res[i] = sum % 10;
        carry = sum / 10;
    }
    // 處理最高位進位...
}

總結

原代碼核心問題是 數組大小 5 與循環上限 5 不匹配導致越界。C 語言數組零基址、半開區間 [0, n) 是肌肉記憶級基本功。斐波那契遞推邏輯本身正確,修正邊界並擴大數組即可得到預期輸出 1 1 2 3 5 8。養成 -Wall -Wextra -fsanitize=address 編譯習慣,能在編譯/運行期捕獲 90% 以上越界錯誤。

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