C语言字符串
字符串
? ??c 語(yǔ)言沒(méi)有專(zhuān)門(mén)用于存儲(chǔ)字符串的變量類(lèi)型,字符串都被存儲(chǔ)在 char 類(lèi)型的數(shù)組中。數(shù)組由連續(xù)的存儲(chǔ)單元組成,字符串中的字符被存儲(chǔ)在相鄰的存儲(chǔ)單元中,每個(gè)單元存儲(chǔ)一個(gè)字符,c 語(yǔ)言用數(shù)組末尾的字符 \o 標(biāo)記字符串的結(jié)束。
? ? ??c 中的字符串一定是以空字符結(jié)束,這意味著數(shù)組的容量必須至少比待存儲(chǔ)字符串的字符數(shù)多 1,以上圖中有14個(gè)存儲(chǔ)單元,卻只能存儲(chǔ)13個(gè)字符,剩下一個(gè)字節(jié)留給空字符。? ? ??
字符串常量
? ? ?用雙引號(hào)括起來(lái)的內(nèi)容稱(chēng)為字符串的字面量,也叫做字符串常量。雙引號(hào)中的字符和編譯器自動(dòng)加入末尾的 \0 字符,都作為字符串存儲(chǔ)在內(nèi)存中,如:” hello world ! ” 、” good morning “ 、 “ i am a student?” 都是字符串字面量。另外注意一點(diǎn),你的字符串字面量之間如果沒(méi)有間隔,或用空白字符分隔,c 會(huì)自動(dòng)將它們串聯(lián)起來(lái)。
#include<stdio.h> int main(void) {char a[]="hello ""world " "!";char b[]="hello world !";printf("a[]=%s b[]=%s\n",a,b);return 0;}它們的輸出是相同的:
字符串變量
我們字符串變量一般有兩種方法創(chuàng)建,指針或者是數(shù)組
#include<stdio.h> int main(void) {char a[]="hello world !"; //數(shù)組char* b=" hello world !"; //指針}? ? 數(shù)組形式( a [ ] )在計(jì)算機(jī)的內(nèi)存中分配為一個(gè)內(nèi)含14個(gè)元素的數(shù)組,每個(gè)元素初始化為字符串字面量對(duì)應(yīng)的字符。通常,字符串都作為可執(zhí)行文件的一部分存儲(chǔ)在數(shù)據(jù)段中。當(dāng)把程序載入內(nèi)存時(shí),也載入了程序中的字符串。字符串存儲(chǔ)在靜態(tài)存儲(chǔ)區(qū)中,但是,程序在開(kāi)始運(yùn)行時(shí)才會(huì)為該數(shù)組分配內(nèi)存。此時(shí)才將字符串拷貝到數(shù)組中,此時(shí)字符串有兩份,一個(gè)是在靜態(tài)內(nèi)存中的字符串字面量,另一個(gè)是存儲(chǔ)在 a[ ] 數(shù)組中的字符串。
文字有點(diǎn)晦澀,我們結(jié)合圖看看??
?指針形式( *b )也使得編譯器為字符串在靜態(tài)存儲(chǔ)區(qū)預(yù)留14個(gè)元素的空間。一旦開(kāi)始執(zhí)行程序,它會(huì)把字符串地址存儲(chǔ)在指針變量中。該變量指向該字符串的首字符。?
其實(shí)不用關(guān)心太多,你只要知道,初始化數(shù)組把靜態(tài)存儲(chǔ)區(qū)的字符串拷貝到數(shù)組中,你的數(shù)組得到的只是它的副本,而初始化指針只把字符串的地址拷貝給指針,你得的是靜態(tài)存儲(chǔ)區(qū)字符串的地址。
數(shù)組和指針的選擇:
? ? ?那么我們用數(shù)組還是用指針呢?它們一個(gè)存著地址一個(gè)存著副本,所以肯定是有差別的對(duì)吧,我們精簡(jiǎn)的了解一下,因?yàn)闀?shū)上真的很復(fù)雜寫(xiě)了一大堆的例子,我們提取一下精華:
? ? ?字符串字面量是?const 的數(shù)據(jù)(常量),由于 *b 指向這個(gè) const 數(shù)據(jù),所以實(shí)際上?b 是?const? char * b ,但是由于歷史的原因,編譯器接受不帶 const 的寫(xiě)法,這意味這不能用 b 改變它指向的數(shù)據(jù),但是仍然可以改變 b 的值,就是讓 b 指向別的位置。如果把一個(gè)字符串字面量拷貝給一個(gè)數(shù)組,就可以隨意改變數(shù)據(jù),除非把數(shù)組聲明為 const,數(shù)組元素是變量,但是數(shù)組名不是變量。
#include<stdio.h> int main(void) {char a[]="hello world !"; //數(shù)組a[0]='H';printf("a[]=%s\n",a);char* b="hello world !"; //指針b[0]='H'; printf("*s=%s\n",b);return 0;}? ??? ? ?
我用的是 Dev?-C++ ,在我電腦上編譯它過(guò)了,但是這個(gè)指針形式并沒(méi)有輸出,這就很好的證明了上面說(shuō)的對(duì)吧,你用指針你不能修改字符串字面量(字符串常量),因?yàn)槟愕闹羔樖?const char *,所以你可以在把指針初始化為字符串字面量時(shí)使用 const 限定符:const char * b,書(shū)上推薦我們這樣用,這也是比較安全的做法,看見(jiàn) const 我們就知道不能去修改它。總之,初始化數(shù)組把靜態(tài)存儲(chǔ)區(qū)的字符串拷貝到數(shù)組中,而初始化指針只把字符串的地址拷貝給指針,如何選擇取決于你想用程序做什么,如果你要去構(gòu)造一個(gè)字符串→數(shù)組,如果你要處理一個(gè)字符串→指針。
補(bǔ)充
? ? ? ?再說(shuō)一下指針,就是當(dāng)你用多個(gè)指針初始化的字符串字面量是一樣的,它們得到的是同一個(gè)地址,編譯器可以使用內(nèi)存中的一個(gè)副本表示所以完全相同的字符串字面量。
#include<stdio.h> int main(void) {char* a="hello world !"; char* b="hello world !"; char* c="hello world !"; printf("a= %p\n",a);printf("b= %p\n",b);printf("c= %p\n",a);return 0;}你看它們的地址是不是一模一樣
?所以你有沒(méi)有懂懂一點(diǎn)點(diǎn)這個(gè)(你初始化指針是 const ),如果允許你修改的話(huà):
?? ?char* a="hello world !";?
?? ?char* b="hello world !";?
?? ?char* c="hello world !";?
?? ?
?? ?printf("a= %p\n",a);
?? ?a[0]='y';? ? ? ? ? ? ? ?
?? ?printf("b= %p\n",b);
?? ?printf("c= %p\n",a);
那后面兩個(gè)輸出都變成“ yello world ”,如果編譯器使用這種單次副本表示法,并允許 a[ 0 ] 修改 ‘ h ’,那將影響所有使用該字符串的代碼。而把數(shù)組初始化為字符串字面量卻不會(huì)導(dǎo)致類(lèi)似問(wèn)題,因?yàn)閿?shù)組獲得的原始字符串的副本。總之,如果你打算修改字符串,就不要用指針去初始化。
?? ?
總結(jié)
- 上一篇: 腾讯企业邮箱api java_腾讯企业邮
- 下一篇: 1600-卡斯丁狗要吃糖葫芦 ZCMU