2013-03-09 43 views
6

我們有一個學校項目,任何使用C的信息系統。爲了保持動態大小的學生記錄列表,我去了一個鏈表數據結構。今天早上,我的朋友讓我看看他的系統。我很驚訝,他的記錄列表:C全局未定義數組?

#include <stdio.h> 
/* and the rest of the includes */ 

/* global unsized array */ 
int array[]; 

int main() 
{ 
    int n; 
    for (n=0; n < 5; n ++) { 
     array[n] = n; 
    } 


    for (n=0; n < 5; n ++) { 
     printf("array[%d] = %d\n", n, array[n]); 
    } 
    return 0; 
} 

與代碼,他宣稱的未分級的數組,它是全球性(在BSS段),整個程序。他能夠通過重寫的存儲器後續塊與零以外的值,以新的條目添加到所述陣列,使得他可以遍歷正是如此陣列:

for (n=0; array[n]; n++) { 
    /* do something */ 
} 
他用

(I也與測試它)的Turbo C V1 。我在linux中試過,它也可以。

因爲我從來沒有遇到過這種技術,我假設它有一個問題。所以,是的,我想知道爲什麼這是一個壞主意,爲什麼更喜歡這個鏈接列表。

+1

這與寫入任何越界數組相同 - 未定義。 – teppic 2013-03-09 14:56:14

+0

這應該是c99嗎? – 2013-03-09 15:03:18

+0

1der請檢查teppic的更新答案。並打開鍵盤鏈接,您可以觀察代碼中C的未定義行爲。 – 2013-03-09 15:22:28

回答

6
int array[]; 

在技術上是已知爲陣列與不完全型。簡單地把它等同於:

int array[1]; 

這是不好的,只是因爲:

  1. 它產生的未定義行爲。具有不完整類型的陣列的主要用途在於Struct Hack。請注意,不完整的數組類型在C99中是標準化的,而且之前是非法的。
+0

是不是隻是UB,因爲GCC說''source.c:4:5:warning:array'array'假定有一個元素[默認啓用],這意味着他會寫入數組邊界之外再往前走1個元素? – 2013-03-09 14:57:13

+2

這不是一個VLA,它只是寫入內存中的一個隨機地址。 – teppic 2013-03-09 14:57:43

+0

@teppic,託尼:是的,修改爲反映正確性。 – 2013-03-09 15:10:13

3

這是未定義的行爲。您正在寫未分配的內存(超出數組)。爲了編譯這個,編譯器至少分配了一個元素,然後你就寫出了這個元素。嘗試更大範圍的數字。例如,如果我在Linux上運行你的代碼,它會起作用,但是如果我將循環更改爲50,000,則會崩潰。

編輯該代碼可能適用於n的較小值,但對於較大的值則會失敗。爲了證明這一點,我已經編寫了你的​​代碼並且對其進行了測試,其代碼爲n = 1000

以下是CODEPAD的鏈接,您可以看到,對於n = 1000,會發生分段錯誤

儘管使用相同編譯器的相同代碼,它工作於n = 10,請參閱此鏈接CODEPAD。所以這被稱爲未定義的行爲

+0

我在你的答案中添加一些更多的細節來演示未定義的行爲代碼。希望你喜歡。如果沒有,你可以恢復到你的版本 – 2013-03-09 15:21:11

+0

@GrijeshChauhan:好的,我會稍微修改它。 – teppic 2013-03-09 15:23:29

+0

是的,繼續。 :) – 2013-03-09 15:26:49

1

如果您使用鏈接列表,您可以檢查內存是否正確分配。

​​

但是用你的代碼,如果用一個大的數組進行測試,程序就會崩潰。