該accepted answer是好的,但不完整。
char * test = "abcdefghijklmnopqrstuvwxyz";
甲字符串文字是指具有靜態存儲持續時間類型char[N]
的一個匿名數組對象(即它存在該程序的整個執行),其中N
是串的長度加上一個用於終止'\0'
。此對象不是const
,但任何修改它的嘗試都有未定義的行爲。 (一個實現可以使字符串文字寫的,如果它選擇,但最現代的編譯器不知道。)
聲明上面創建char[27]
類型,例如一個匿名對象,並使用該對象的第一個元素的地址來初始化test
。因此像test[5] = 'x'
這樣的分配嘗試修改數組,並且具有未定義的行爲;通常會導致程序崩潰。 (初始化使用地址,因爲文字是數組類型的表達式,它在大多數上下文中被隱式轉換爲指向數組第一個元素的指針。)
注意,在C++中,字符串實際上是const
,和上面的聲明是非法的。在C或C++,最好聲明test
爲指針,以常量char
:
const char *test = "abcdefghijklmnopqrstuvwxyz";
所以編譯器會警告你,如果你嘗試通過test
修改數組。
(由於歷史原因,C字符串文字不是const
在1989 ANSI C標準之前const
關鍵字不存在要求它被用於像你這樣的聲明中會使用更安全的代碼但它會要求現有的代碼進行修改,一些ANSI委員會試圖避免的。你應該假裝該字符串字面量const
,儘管事實並非如此。如果你碰巧使用gcc,該-Wwrite-strings
選項將導致編譯器把字符串文字爲const
- 這使得GCC不符合)
如果你希望能夠修改字符串。指的是,你可以將其定義是這樣的:
char test[] = "abcdefghijklmnopqrstuvwxyz";
編譯器着眼於初始確定test
需要有多大是。在這種情況下,test
將是char[27]
類型。字符串文字仍然指的是一個匿名的大部分只讀數組對象,但它的值是將複製到test
中。 (在用於初始化一個數組對象的初始化字符串文字是其中的陣列不「衰減」的指針的上下文中的一個;所述其它的是當它的一元&
或sizeof
操作數。)由於不存在進一步的對匿名數組的引用,編譯器可以優化它。
在這種情況下,test
本身是一個包含您指定的26個字符的數組,加上終止符'\0'
。該陣列的生命週期取決於test
的聲明位置,這可能並不重要。例如,如果您這樣做:
char *func(void) {
char test[] = "abcdefghijklmnopqrstuvwxyz";
return test; /* BAD IDEA */
}
調用者將收到一個指向不再存在的指針。如果需要參考範圍之外的陣列,其中test
被定義,則可以將其定義爲static
,也可以使用malloc
分配它:
char *test = malloc(27);
if (test == NULL) {
/* error handling */
}
strcpy(test, "abcdefghijklmnopqrstuvwxyz";
所以該陣列將繼續存在,直到調用free()
。非標準的strdup()
函數執行此操作(它由POSIX定義,但不由ISO C定義)。
仔細注意test
可以是指針或取決於你如何聲明一個數組。如果您將test
傳遞給字符串函數,或傳遞給任何採用char*
的函數,則無關緊要,但類似sizeof test
的行爲會有很大差異,具體取決於test
是否爲指針或數組。
的comp.lang.c FAQ非常出色。第8部分涵蓋字符和字符串,第8.5部分問題涉及問題1.32,它解決了您的具體問題。第6節介紹了數組和指針之間經常令人困惑的關係。
我討厭這麼說,但這確實應該在某個C語言常見問題解答中......在Stack Overflow中已經有數十次或數百次的問題了。 – ephemient 2009-09-21 19:44:44
如果之前已詢問過此問題,我很抱歉,但無法找到答案。我確實首先閱讀了函數參考和所有內容,但是我確實沒有看到我做錯了什麼。你能指點我這樣一個C FAQ嗎? – fresskoma 2009-09-21 20:58:06
@ x3ro:4年內沒有人回答您有關C FAQ的問題? [comp.lang.c FAQ](http://www.c-faq.com/)非常好。第8部分涵蓋字符和字符串,第8.5部分問題涉及問題1.32,它解決了您的具體問題。 – 2013-09-28 20:24:57