2009-06-20 321 views
11

我一直在閱讀K & R關於C的書,並發現C中的指針算術允許訪問超出數組末尾的一個元素。我知道C允許用記憶做任何事情,但我只是不明白,這個特點的目的是什麼?C元素超出數組的末尾

+1

另請參閱此問題:http://stackoverflow.com/questions/988158/take-the-address-of-a-one-past-the-end-array-element-via-subscript-legal-by- – 2009-06-20 14:07:03

回答

19

C不允許訪問超出陣列末尾的內存。但是,它確實允許指針指向超出數組末尾的一個元素。區別很重要。

因此,這是確定:

char array[N]; 
char *p; 
char *end; 

for (p = array, end = array + N; p < end; ++p) 
    do_something(p); 

(做*end將是一個錯誤。)

和表示之所以這個功能是非常有用的:在(不存在的一個指針指向)元素在數組結束後可用於比較,比如在循環中。

從技術上講,這是C標準允許的一切。但是,實際上,C實現(編譯器和運行時)不會檢查您是否訪問超出數組末尾的內存,無論它是否是一個或多個元素。必須進行邊界檢查,這會減慢程序的執行速度。程序C的種類最適合(系統編程,通用庫)比安全性和安全性邊界檢查更有利於速度。

這意味着C可能不是通用應用程序編程的好工具。

15

通常,它是表示「結束」的位置,這是一個過去的實際分配有用的,所以您可以編寫代碼:

char * end = begin + size; 
for (char * curr = begin; curr < /* or != */ end ; ++curr) { 
    /* do something in the loop */ 
} 

C標準明確地說,這個元素是一個有效的內存地址,但取消引用它仍然不是一個好主意。

它爲什麼有這個保證?假設您有一臺內存爲2^16字節的機器,地址爲0000-FFFF,16位指針。假設你創建了一個16字節的數組。內存可以分配在FFF0嗎?

有16個字節可用連續的,但:

begin + size == FFF0 + 10 (16 in hex) == 10000 

它包裝爲0000,因爲指針的大小。現在環路條件:

curr < end == FFF0 < 0000 == false 

而不是遍歷數組,循環將無所作爲。這會破壞很多代碼,所以C標準說分配是不允許的。

-1

,你可以遠遠超出過去1陣列 爲example`

int main() 
{ 
     char *string = "string"; 
     int i = 0; 
     for(i=0; i< 10;i++) 
     { 
       printf("%c\n", string[i]); 
     } 
     return 0; 
} 

串詞,無論是坐在內存前手結束後,將打印垃圾。

+6

它可能會打印垃圾,格式化硬盤,或導致惡魔飛出你的鼻子;這是未定義行爲的性質。 – aib 2009-06-20 05:57:19