字符串是以ASCII字符NUL結尾的字符序列。ASCII字符NUL表示為\0.字符串通常存儲在數組或者從堆上分配的內存中。不過,並非所有的字符數組都是字符串,字符數組可能沒有NUL字符。字符數組也用來表示布爾值等小的整數單元,以節省內存空間。
C中有兩種類型的字符串:
單字節字符串
由char數據類型組成的序列
寬字符串
由wchar_t數據類型組成的序列
wchar_t數據類型用來表示寬字符,要麼是16位寬,要麼是32位寬。這兩種字符串都以NUL結尾。可以在string.h中找到單字節字符串函數,而在wchar.h中找到寬字符串函數。寬字符主要用於非拉丁字符集,對於支持外語的應用程序很有用,
字符串的長度是字符串中除了NUL字符外的字符數。為字符串分配內存的時候,要記住為所有的字符加上NUL字符分配足夠的空間。
NULL和NUL不一樣。NULL用來表示特殊的指針,通常定義為((void*)0),而NUL是一個char,定義為\0,兩者不能混用!
字符常量是單引號引起來的字符序列。字符常量通常由一個字符組成,也可以包含多個字符,比如轉義字符。在C中,它們的類型是int,如下所示:
printf("%d\n",sizeof(char)); printf("%d\n",sizeof('A')); //output //1 //4
聲明字符串的方法有三種:字面量,字符數組,和字符指針。
字符串字面量是用雙引號引起來的字符序列,常用來進行初始化,他們位於字符串字面量池中。這和單引號引起來的字符不一樣!
下面是一個字符數組的例子:
char header[32];
下面是字符指針:
char *header;
定義字符量通常會將其分配到字面量池中,這個內存區域保存了組成字符串的字符序列。多次會用到同一個字面量時,字面量池通常會只有一個副本。這樣可以減少應用程序占用的內存。通常認為字面量是不可變的,因此只有一份副本不會有什麼問題。
字符串字面量一般分配在只讀區域中,所以是不可變的。字符串字面量在哪裡使用,或者他是全局,靜態或者局部都無所謂,從這個角度講,字符串字面量不存在作用域的概念。
在大部分編譯器中,我們將字符串字面量看做常量,無法修改字符串。但是GCC編譯器容許字符串字面量可以修改。
char *header = "Sound"; *header = 'L'; printf("%s\n",header); //output //Lound
這樣就會改變字符串,不是我們預期的結果。因此應該避免這樣做。像下面這樣把變量聲明為常量可以解決一部分問題。任何修改都會造成編譯時錯誤:
const char *header = "Sound";
初始化字符串采用的方法取決於變量是被聲明為字符數組還是字符指針,字符串所用的內存要麼是指針指向的一塊內存。我們都可以用字符串字面量或者一些列字符初始化字符串,或者從別的地方(標准輸入)得到字符。
我們可以用初始化操作符初始化char數組。在下例中,header數組被初始化為字符串字面量中所包含的字符:
char header[] = "Media Player";
字符量"Media Player"的長度為12,表示這個字面量需要13個字節,我們就要為數組分配13個字節來持有字符串。初始化操作會把這些字符復制到數組中,以NUL結尾。
我們也可以用strcpy函數來初始化數組。
用動態內存分配來初始化char指針。
char *header; char *header = (char*)malloc(strlen("Media Player")+1);
注意不要用sizeof操作符,而要用strlen函數來確定已有字符串的長度,sizeo操作符會返回數組和指針的長度,而不是字符串的長度。