在代碼char * str = "hello";
中,我知道代碼"hello"
是將單詞hello分配給任何其他記憶體,然后將分配的記憶體的第一個值放入變數 str。
但是當我使用代碼時char str[10] = "hello";
,我了解到hello這個詞包含在陣列的每個元素中。
如果然后,在頂部,代碼"hello"
回傳記憶體的地址,在底部,代碼"hello"
回傳單詞 hello \n。
我想知道它們為什么不同,如果我錯了,我想知道雙引號回傳什么。
uj5u.com熱心網友回復:
C有點古怪。這里有兩個不同的用例。但是,讓我們首先從是什么開始"hello"
。
你"hello"
在程式源代碼中是一個字串文字。那是一個用雙引號括起來的字符序列。當編譯器編譯這個源代碼時,它會在序列中附加一個零位元組,這樣標準庫函式strlen()
就可以對其進行處理。然后編譯器使用生成的以零結尾的序列來“初始化一個靜態存盤持續時間和長度的陣列,剛好足以包含常量字符的序列陣列”(n1570 ISO C 草案,6.4.5/6)。該長度為 6:5 個字符 h、e、l、l 和 o 以及附加的零位元組。
“靜態存盤持續時間”是指陣列在程式運行的整個程序中都存在(與具有自動本地存盤持續時間的物件相反,例如區域變數,以及通過或創建的具有動態存盤持續時間的物件)。malloc()
calloc()
您可以記住該陣列的地址,如char *str = "hello";
. 該地址將指向程式生命周期內的有效記憶體。
第二個用例是用于初始化字符陣列的特殊語法。它只是這個常見用例的語法糖,并且與您通常無法使用陣列初始化陣列的事實背道而馳。1
這次您不定義指標,而是定義了一個適當的 10 個字符陣列。然后,您使用字串文字對其進行初始化。您始終可以使用通用方法通過在花括號中列出以逗號分隔的各個陣列元素來初始化字符陣列(順便說一下,此通用方法也適用于其他型別的復合型別,即結構):
char str[10] = { 'h', 'e', 'l', 'l', 'o', '\0' };
這完全等同于
char str[10] = "hello";
現在您的陣列的元素(10)比從字串文字(6)產生的初始化陣列中的字符數更多;該標準規定“未顯式初始化的子物件應被隱式初始化,與具有靜態存盤持續時間的物件相同”。那些全域變數和靜態變數初始化為零,這意味著字符陣列str
以 4 個零字符結尾。
很明顯,為什么 Dennis Ritchie 通過字串文字添加了有點反范式的字符陣列初始化,可能是在他第二次不得不使用通用陣列初始化語法之后。設計自己的語言有它的好處。
1例如,不起作用。你必須使用static char src[] = "123"; char dest[] = src;
strcpy()
.
uj5u.com熱心網友回復:
初始化:
char * str = "hello";
在大多數 C 實作中,確保將字串hello
放置在可執行記憶體的常量資料部分中。正好寫入了六個位元組,最后一個是字串終止符'\0'
。
str
char 指標包含第一個字符的地址'h'
,因此任何訪問該字串的人都知道必須讀取以下位元組,直到找到終止符為止。
其他初始化
char str[10] = "hello"; // <-- string must be enclosed in double quotes
非常相似,因為str
指向字串的第一個字符,并且后面的字符被寫入下面的記憶體位置(包括字串終止符)。
但是:
- 即使只有六個位元組被顯式初始化,也會分配十個位元組,因為這是陣列的大小。在這種情況下,四個尾隨位元組將包含零
- 資料不是常量,可以更改,而在前面的示例中,這是不可能的,因為在大多數 C 實作中,這種初始化指示編譯器使用常量資料部分
uj5u.com熱心網友回復:
你似乎混淆了一些事情:
char str[10] = "hello';
這甚至不能編譯:當你以雙引號開頭時,你應該以一個結尾:
char str[10] = "hello";
在記憶體中,這具有以下效果:
str[0] : h
str[1] : e
str[2] : l
str[3] : l
str[4] : o
str[5] : 0 (the zero character constant)
str[6] : xxx
str[7] : xxx
str[8] : xxx
str[9] : xxx
(xxx
我的意思是這可以是任何東西)
結果,代碼將不會回傳hello\n
(帶有行尾字符),而只會回傳hello\0
(零字符)。
雙引號僅提及字串常量的開頭和結尾,不回傳任何內容。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507338.html