[英]What is going on in these five different ways of declaring a cString?
另一個問題(我現在找不到的)的解釋是“字符串”和{'s','t','r','i','n','g','\\ 0'}等價。 實際上,下面的前四個聲明都編譯並且似乎做同樣的事情。 但那為什么第五個聲明不編譯? 看起來它們畢竟不是等同的。 所以我的問題是四個正確的和一個不正確的cstring聲明究竟發生了什么?
int main()
{
char cString1[]="string";
char * cString2 = "string";
char cString3[] = {'s','t','r','i','n','g', '\0'};
char cString4[7] = {'s','t','r','i','n','g','\0'};
char * cString5 = {'s','t','r','i','n','g','\0'};
return 0;
}
聲明並不完全等效:第一,第三和第四聲明構成字符串文字的可寫副本,而第二聲明不制作副本。 結果,做出這樣的任務是合法的
cString1[0] = 'S'; // cString3 and cString4 would work as well
嘗試使用cString2
執行相同cString2
會觸發未定義的行為。
第三和第四個聲明是相同的,除了數字3允許編譯器計算出數組的大小,而數字4則明確指定它。 你可以像這樣重寫第一個聲明
char cString1a[7]="string";
遵循相同的模式。
雖然"string"
可以在數組聲明中重寫為{'s','t','r','i','n','g','\\0'}
,但在上下文中它是不合法的初始化指針。 這就是為什么最后一個聲明不起作用的原因。
但是,在c99中,您可以使用復合文字重寫它以使其工作( 演示 ):
char * cString5 = (char[]){'s','t','r','i','n','g','\0'};
他們(顯然)不等同。
"string"
是一個靜態的字符數組,包含字符's','t','r','i','n','g','\\0'
。 但是, {stuff}
是初始化列表 。 它是用於初始化左側的靜態元素數組。 數組衰減到指針,但初始化列表不會,因為它不是數組。 更令人困惑的是,在C和C ++中有一個特殊情況,即char[]
可以從字符串文字初始化,即使通常通過“復制”初始化數組也是非法的。
char cString1[]="string"; //special case for string literal array copy
char * cString2 = "string"; //array decays to pointer
char cString3[] = {'s','t','r','i','n','g', '\0'}; //constructing array from list
char cString4[7] = {'s','t','r','i','n','g','\0'}; //constructing array from list
char * cString5 = {'s','t','r','i','n','g','\0'}; //list DOES NOT decay to pointer.
char cString7[7] = "string"; //also special case for string literal array copy
正如dasblinkenlight所指出的,其中兩個是指向靜態數據的指針,而其中三個是通過從靜態數據復制而初始化的本地數組。 它們相似,但不一樣。
"string"
和{'s','t','r','i','n','g','\\0'}
等價
作為字符數組的初始化,是的。 在其他情況下,沒有。
下面的前四個聲明都編譯並且似乎做同樣的事情。
不,他們沒有; 其中三個聲明數組,而兩個(嘗試)聲明指針。
但那為什么第五個聲明不編譯?
因為它試圖用不適合初始化指針的東西初始化指針。
在四個正確的和一個不正確的cstring聲明中究竟發生了什么?
第一個聲明一個本地數組,通過將字符串文字(包括其終結符)復制到其中來初始化。 從文字推斷出大小。
第二個聲明一個本地指針,初始化為指向字符串文字。 文字本身是一個const char
的靜態數組。 現代編譯器不應該接受這個,因為文字是const
但指針不是。 舊版本的語言接受了這種狡猾的轉換,以便與古代代碼兼容。
第三個聲明了一個從列表初始化的本地數組。 從列表中推斷出大小。 結果與第一個相同。
第四個與第三個相同,但明確指定大小。
第五個是無效的; 指針必須指向一個對象(或為null),初始化列表不是一個對象。
在C ++中,使用std::string
來表示字符串通常更方便,而不是使用低級數組和指針。
char cString1[]="string";
聲明一個未指定大小的char
數組(由編譯器計算)並使用7 char
的const數組(包括'\\0'
終止符)初始化它
char * cString2 = "string";' declares a pointer to
char * cString2 = "string";' declares a pointer to
char char * cString2 = "string";' declares a pointer to
and initializes it with a const array of 7
字符and initializes it with a const array of 7
(including the
'\\ 0'`終止符)
char cString3[] = {'s','t','r','i','n','g', '\\0'};
就像第一個一樣,除了在這種情況下,初始化數組是明確定義的char-by-char,包括終結符。 注意,如果省略此代碼中的終結符,則字符串將無法終止,並且可能導致程序訪問無效內存(例如,在嘗試打印該字符串時)
char cString4[7] = {'s','t','r','i','n','g','\\0'};
就像前一個一樣,除了你定義數組的大小。 如果你在初始化數組中有比你指定的更多(或更少!)元素 - 編譯器會對此感到高興
char * cString5 = {'s','t','r','i','n','g','\\0'};
是非法的,因為你聲明了一個指向char
的指針,但是用一個char
數組初始化它
cString1是1個對象[0]的字符串數組[]
cString2是一個包含6個字符的字符串
cString3是7個對象的字符串數組[] [7]
cString4是一個7對象的字符串數組[7] [7]
cString5是您嘗試聲明為7個對象的字符串
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.