從愚蠢的錯誤學習

記錄一下今天犯的愚蠢錯誤,先來看看錯誤的程式碼:

輸入檔內容:

3 4 4 4 5 5 5 1 2 3
程式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#include usingnamespace std;

int main(int argc, constchar*argv[]){
    int n =0;
    int weight[n][n];
    int dis[n];
    int parent[n];
    bool visited[n];

cin>> n;
    for(int i =0; i < n;++i){
        for(int j =0; j < n;++j){
            int w =0;
            cin>> w;
            weight[i][j]= w;
        }
    }
    for(int i =0; i < n;++i){
        for(int j =0; j < n;++j){
            cout<< weight[i][j]<<" ";
        }
        cout<< endl;
    }
}

最後的輸出竟然是:

3 1 2 3 1 2 3 1 2 3
一開始猜想可能是 for 迴圈中打錯字或是忘記 ++ 之類的,甚至還重寫了一個檔案來 diff,過了許久才發現這愚蠢的 bug: **在還沒有讀取到 stdin 的數值之前,我就拿 n 來宣告了所有的陣列大小!**

不過最奇妙的是,這個是不會產生 segmentation fault 的!而且還可以順利列印出數值(雖然是錯的),於是我加了以下程式列印出記憶體位址與大小:

    printf("weight addr: %x\n", &weight[1]);     printf("weight size: %u\n", sizeof(weight));     printf("dis addr: %x\n", &dis);     printf("dis size: %u\n", sizeof(dis));     printf("parent addr: %x\n", &parent);     printf("parent size: %u\n", sizeof(parent));     printf("visited addr: %x\n", &visited);     printf("visited size: %u\n", sizeof(visited));
輸出結果如下:
weight addr: bfffe6b0 weight size: 0 dis addr: bfffe6a0 dis size: 0 parent addr: bfffe690 parent size: 0 visited addr: bfffe680 visited size: 0
因為堆疊由記憶體位址高往低放,所以列印出來的位址是遞減的,比較特別的是為了驗證奇怪的輸出結果,上面程式是選擇列印 weight[1] 的位址而不是 weight。因此我們可以得出結論,只要是宣告為陣列,即使大小為零,編譯器還是會為這些陣列保留最小的固定空間,在我電腦上的情況是保留 16 bytes。