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

2.1.1 字符串數據類型

字符串由一個以第一個空(null)字符作為結束的連續字符序列組成,并包含此空字符。一個指向字符串的指針實際上指向該字符串的起始字符。字符串長度指空字符之前的字節數,字符串的值則是它所包含的按順序排列的字符值的序列。圖2.1顯示“hello”的字符串表示形式。

圖2.1 “hello”的字符串表示形式

字符串實現為字符數組而且容易遭受與數組同樣的問題。

因此,適用于數組的安全編碼實踐也應當應用于以空字符結尾的字符串,參見《C安全編碼標準》[Seacord 2008]的“數組(ARR)”一章。在處理數組時,定義一些術語很有用,如下所示。

界限(Bound)

數組中的元素個數。

低位地址(Lo)

數組首元素地址。

高位地址(Hi)

數組末元素地址。

TooFar

數組最遠端的元素之后加1位置的元素地址,這個元素正好在Hi元素之后。

目標大小(Tsize)

與sizeof(array)相同。

C標準允許創建指向數組對象的末元素之后加1位置的指針,雖然這些指針無法在不產生未定義行為的狀況下解引用。在處理字符串時,以下額外的術語也很有用:

空字符結尾(Null-terminated)

在Hi或它之前,存在空終結符。

長度(Length)

空終結符之前的字符數量。

數組大小。數組帶來的問題之一是確定其元素數量。下面例子中,函數clear()使用慣用的sizeof(array)/sizeof(array[0])來確定數組中的元素數量。但是,因為array是一個參數,所以它的類型是指針。 [1]因此,sizeof(array)等于sizeof(int *)。例如,在sizeof(int)==4且sizeof(int *)==4的架構(如x86-32)中,無論傳入的數組的長度是多少,表達式sizeof(array)/sizeof(array[0])的計算結果都為1,數組的其余部分不影響此結果。


01 void clear(int array[]) {
02 for (size_t i = 0; i < sizeof(array) / sizeof(array[0]); ++i) {
03 array[i] = 0;
03 array[i] = 0;
04 }
05 }
06
07 void dowork(void) {
08 int dis[12];
09
10 clear(dis);
11 /* ... */
12 }

這是因為sizeof運算符在應用于聲明為數組或函數類型的參數時,它產生調整后的(即指針)類型大小。strlen()函數可以用來確定一個正確地以空字符結尾的字符串的長度,但不能用來確定一個數組的可用空間。《C安全編碼標準》[Seacord 2008]涉及“ARR01-C.在獲取一個數組的大小時,不要對一個指針應用sizeof運算符”,該規則針對這個問題提出了警告。

一個字符串中的字符都屬于在執行環境中解釋的字符集—執行字符集。這些字符由C標準定義的一個基本字符集和一組零個或多個擴展字符(它們不是基本字符集的成員)組成。執行字符集的成員的值是具體實現定義的,但可能(例如)是美國7位ASCII字符集的值。

C使用一個語言環境(locale)的概念,它可以由setlocale()函數改變,用來跟蹤各種約定,如具體實現支持的語言和標點符號。當前語言環境確定哪些字符可用作可擴展字符。

基本執行字符集包括拉丁字母表的26個大寫字母和26個小寫字母、10個十進制數字、29個圖形字符、空格字符,以及表示水平制表符、垂直制表符、換頁符、警告、退格鍵、回車和換行符的控制字符。基本字符集的每個成員都適合用單個字節表示。基本執行字符集中必須存在一個字節的所有位都設置為0的字符,稱為空字符(null),它是用來終止字符串的。

執行字符集可能包含大量的字符,因此需要多個字節來表示擴展字符集中的一些單個字符。這就是所謂的多字節(multibyte)字符集。在這種情況下,基本字符仍然必須存在,并且基本字符集的每個字符都編碼為單字節。任何額外字符的存在、含義和表示都是特定于語言環境的。一個字符串,可能有時會稱為一個多字節字符串,以強調它可能會存在多字節字符。這些與寬字符串不同,因為在寬字符串中每個字符都具有相同的長度。

一個多字節字符集,可能有狀態相關(state-dependent)的編碼,其中每個多字節字符序列開始于初始變換狀態,并當在序列中遇到特定的多字節字符時進入其他特定語言環境的變換狀態。當在初始變換狀態中,所有的單字節的字符保留它們通常的含義,并且不變更變換狀態。在序列中后續字節的含義是當前變換狀態的一個函數。

[1] 這里指array是clear()函數的參數,數組名作函數參數會被C 語言轉換為指針,而不是sizeof 的“參數”, 因為sizeof不是函數, 而是運算符, 如果直接在dowork()函數中計算sizeof(dis),結果將是12*sizeof(int)。—譯者注
主站蜘蛛池模板: 邢台市| 许昌市| 蒲城县| 喀什市| 申扎县| 遵义市| 江山市| 喀喇沁旗| 晋城| 娱乐| 大足县| 苏尼特右旗| 台北市| 闽侯县| 时尚| 法库县| 札达县| 潍坊市| 塘沽区| 安宁市| 平罗县| 宿松县| 祁阳县| 固安县| 莱芜市| 民县| 林州市| 信丰县| 成武县| 三明市| 贵阳市| 黄平县| 张家界市| 玉山县| 南开区| 廉江市| 乾安县| 视频| 江口县| 蒙城县| 维西|