簡體   English   中英

在 C 中訪問超出數組末尾的元素

[英]Access element beyond the end of an array in C

我一直在閱讀 K & R 關於 C 的書,發現 C 中的指針運算允許訪問數組末尾之外的一個元素。 我知道 C 允許用內存做幾乎任何事情,但我只是不明白,這種特殊性的目的是什么?

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 可能不是通用應用程序編程的好工具。

通常,表示“結束”位置很有用,它是實際分配后的位置,因此您可以編寫如下代碼:

 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 標准說分配是不允許的。

如果您讀取或寫入超出分配的內存,那么 C 標准會說它的“未定義行為”。 這意味着幾乎任何事情都可能發生,也許現在,也許在一周內,也許在 5 年后,也許永遠不會發生,而您卻僥幸逃脫。

我的老板有幾句格言:“沒有正確的 C 程序,只有尚未出錯的程序”“關於內存損壞,你能說的唯一明智的話就是什么都沒有。”

他總是對的。

例如,您可以遠遠超出數組的 1

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

將在字串結束后打印垃圾,無論之前坐在內存中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM