官术网_书友最值得收藏!

2.1.4 字符串字面值

一個字符串字面值是一個包圍在雙引號中的零個或更多個字符的序列,比如"xyz"。寬字符串字面值除了以字母L作為前綴外,其他的表示方式與字符串字面值相同,比如L"xyz"。

在一個字符常量或字符串字面值中,在執行期間使用的字符集的成員,用源代碼中字符集的相應成員表示,或由反斜杠(\)后跟一個或多個字符的轉義序列表示。基本執行字符集必須存在一個所有位為0的字節,稱為空字符,它用來終止字符串。

在編譯期間,由相鄰的字符和具有相同前綴的字符串字面量標記的任意序列指定的多字節字符序列,拼接成單個多字節字符序列。如果其中任何一個標記有編碼前綴,那么由此產生的多字節字符序列就視為具有相同的前綴;否則,把它作為一個字符串字面值對待。不同前綴的寬字符串字面值的標記是否可以聯接(并且,如果是這樣,對由此產生的多字節字符序列的處理)是具體實現定義的。例如,下面的相鄰字符串字面值的標記序列


"a" "b" L"c"
"a" L"b" "c"
L"a" "b" L"c"
L"a" L"b" L"c"

都等于字符串字面值


L"abc"

接下來,把一個值為0的字節或編碼附加到每個由一個或多個字符串字面值形成的字符序列的末尾。(一個字符字串字面值不一定是一個字符串,因為,其中可能會用一個\0的轉義序列嵌入一個空字符。)該字符序列然后用于初始化一個持續靜態存儲的數組,其長度正好足以包含此序列。對于字符串字面值,數組中的元素類型為char,并用字符序列中的每個字節初始化。對于寬字符串字面值,數組中的元素類型為wchar_t,并用對應于該字符序列的寬字符序列進行初始化,這個寬字符序列是由一個實現定義的當前語言環境的mbstowcs()(多字節字符串到寬字符串)函數定義的。含有不在執行字符集中表示字符或轉義序列的一個字符串字面值的值是具體實現定義的。

在C中,字符串字面值的類型是一個char數組,但在C++中,它是一個const char數組。因此,一個字符串字面值在C中是可修改的。然而,如果程序試圖修改這樣的一個數組,該行為是未定義的,因此這種行為是 《C安全編碼標準》[Seacord 2008],“STR 30-C.不要試圖修改字符串字面值”禁止的。制定這條規則的原因之一是,如果這些數組的元素有適當的值,在C標準中沒有規定這些數組必須是不同的。例如,編譯器有時會把多個相同的字符串字面值存儲在相同的地址中,這樣導致修改一個這樣的字面值可能也會改變其他字面值。制定這條規則的另一個原因是,字符串字面值經常存儲在只讀存儲器(ROM)中。

C標準允許在聲明一個數組變量時,既包括界限索引又包括一個初始化字面值。初始化字面值也蘊含著一個數組大小,即其中指定的元素數量。對于字符串,一個字符串字面值指定的大小是字面值中的字符數再加上1(用于終止的空字符)。

數組變量常常由一個字符串字面值進行初始化,并且聲明為一個與字符串字面值中的字符數目相匹配的顯式界限。例如,下面的聲明使用一個字符串字面值初始化了一個字符數組,此字面值比數組能容納的字符多一個字符(包括終結符'\0'):


const char s[3] = "abc";

雖然字符串字面值的大小是4,但數組s的大小是3,因此,尾隨的空字節被刪除。任何隨后將數組作為一個空字節結尾的字符串的使用都會導致漏洞,因為s沒有正確地以空字符結尾。

一個更好的方法是,對于一個用字符串字面值初始化的字符串,不指定它的界限,因為編譯器會自動為整個字符串字面值分配足夠的空間,包括終止的空字符:


const char s[] = "abc";

因為即使字符串的字面值的大小變化了,數組大小總是可以獲得的,所以這種方法還簡化了維護工作。這一問題已被《C安全編碼標準》[Seacord 2008]進一步描述為,“STR 36-C。不要指定一個用字符串字面值初始化的字符數組的界限?!?/p>

主站蜘蛛池模板: 洱源县| 怀宁县| 汉沽区| 拜泉县| 称多县| 古田县| 满洲里市| 合作市| 汤阴县| 巍山| 周宁县| 静宁县| 江阴市| 双柏县| 如皋市| 修文县| 通州市| 平南县| 正定县| 邹城市| 南华县| 新绛县| 怀安县| 万宁市| 竹北市| 浙江省| 堆龙德庆县| 北安市| 小金县| 子长县| 茌平县| 玉林市| 逊克县| 盐城市| 阜平县| 阜南县| 宁晋县| 丰县| 德庆县| 静海县| 绵阳市|