字符串文字不能被修改(沒有未定義的行爲)的主要原因是支持字符串文字合併。編譯器作者注意到很多程序都有相同的字符串文字重複多次 - 尤其是像模式字符串傳遞到fopen
(例如,f = fopen("filename", "r");
)和簡單格式字符串傳遞到printf
(例如,printf("%d\n", a);
)。
爲了節省內存,他們會避免爲這些字符串的每個實例分配單獨的內存。相反,他們會分配一個一塊內存,並指向它的所有指針。
在少數情況下,它們甚至比這更復雜,以合併甚至完全相同的文字。例如,考慮這樣的代碼:
printf("%s\t%d\n", a);
/* ... */
printf("%d\n", b);
在這種情況下,字符串文字不完全相同,但第二個是第一端部的相同部分。在這種情況下,他們仍然會分配一塊內存。一個指針指向內存的開始位置,另一個指向同一塊內存中的%d
位置。
有可能(但沒有要求)字符串文字合併,當修改字符串文字時,說出你會得到什麼樣的行爲是不可能的。如果合併字符串文字,修改一個字符串文字可能會修改其他相同或相同的結尾。如果字符串文字不合並,修改一個將不會影響其他任何文字。
MMU增加了另一個維度:它們允許內存被標記爲只讀,所以嘗試修改字符串文字會導致某種信號 - 但只有當系統有MMU時(通常是可選的一次),也取決於編譯器/鏈接器是否決定將字符串文字放在內存中,它們是否標記爲常量。
由於他們無法定義修改字符串文字時的行爲,他們決定修改字符串文字會產生未定義的行爲。
第二種情況完全不同。在這裏你定義了一個數組char
。很明顯,如果你定義了兩個單獨的數組,它們仍然是獨立的,不管內容如何,所以修改一個不會影響另一個。行爲是清楚的,而且一直都是這樣,所以這樣做給定了行爲。有問題的數組可能是從字符串文字初始化的事實不會改變這一點。
http://stackoverflow.com/a/30661089/2912665 – CinCout
無論是作爲重複關閉的問題還是由@HappyCoder提及的問題都非常類似於此問題。它們都處理字符串文字的類型。這是問**爲什麼**字符串文字有這種類型。 –
不只是「會更好」; 「將是合法的」。你知道這已被問了一百萬次。 –