簡體   English   中英

這五種聲明cString的方式發生了什么?

[英]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.

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