皮拉夫大王編程 2019-09-03 17:15:00 字符數(shù)組現(xiàn)在讓我們把已經(jīng)習(xí)慣的int型數(shù)組轉(zhuǎn)換為char型。一般來講,char型數(shù)組通常是用于'a', 'b', 'c', 'd'這類具有可讀性的字符。在《類型與變量》一節(jié)中講過,char類型的數(shù)據(jù)占用1個字節(jié)的存儲空間,本質(zhì)上它是一種小整型類型。這表明char型數(shù)組也可用來處理數(shù)據(jù),如保存一張圖像的像素值,保存接收到來自服務(wù)器的回復(fù)信息等。隨著以后對指針的深入理解,我們會對此有更深的見解。此時,我們只用它來處理可閱讀字符。 首先,讓我們嘗試輸出"hello"這個字符串,不同的是,這次是使用數(shù)組輸出。 為了明確的看到各種輸出之間的不同,我以大寫串END_STR來標(biāo)識當(dāng)前輸出的結(jié)束。
分析后兩項輸出最后兩個"hello",我們都是使用printf函數(shù)加%s格式符輸出,為什么最后一個亂碼了?最明顯的不同之處在于數(shù)組的定義。str2的最后一個字符是'\0'值,而str1沒有這個值。這說明這個'\0'有特殊意義。 我們知道數(shù)組傳遞給函數(shù)時,會轉(zhuǎn)換為對應(yīng)的指針類型,也就是說str2、str1傳遞給printf函數(shù)時,實際會形成類似printf( char *str )形式?;叵胍幌掠嬎銛?shù)組平均值的函數(shù),對于傳遞數(shù)組的函數(shù),除了數(shù)組變量本身外,通常還需要一個int變量以指明數(shù)組元素的個數(shù)。而我們把str2,str1傳遞給printf函數(shù)時,并沒有給定元素的個數(shù)! 但是由于str2具有特殊標(biāo)記'\0',%s格式符對于該字符數(shù)組輸出了正確值,但str1卻沒有這么幸運,它亂碼了!這就說明了,'\0'指示了字符串的結(jié)束,如同給函數(shù)間接傳遞了元素個數(shù)一般。實際情況也確實如此,當(dāng)printf+%s輸出char*類型時,碰到'\0'就認(rèn)為字符串結(jié)束了。 '\0'結(jié)束字符串可以看到,"world"沒有被輸出,這表明C的字符串是以'\0'表示 “我的話講完了”。 那'\0'到底是什么呢?咳咳~~,又到了說說ASCII碼表的時候了!'\0'是一個轉(zhuǎn)義字符,它代表的是ASCII碼值為0的值,也是ASCII碼表中的第一個值,在C語言中用于表示字符串結(jié)尾標(biāo)記。 注意數(shù)值0與字符'0'是不同的概念,字符'0'可以理解為是書寫上用于交流0值的0。 動手試一下現(xiàn)在你可以嘗試將第一個'\0'變?yōu)閿?shù)值0,你會發(fā)現(xiàn)得到同樣的輸出。再嘗試將0變?yōu)樽址?0',再次觀察輸出并思考一下。假如你一直跟隨我們的教程在學(xué)習(xí),還是有點緊張你會用什么樣的方式來完成這個試驗?zāi)兀课覀円呀?jīng)學(xué)習(xí)過數(shù)組的基礎(chǔ)操作,希望你能使用下標(biāo)運算符去修改數(shù)組中的某個值,而不是把代碼拷貝多份...... 讓生活再簡單點假定你現(xiàn)在在編寫一款RPG游戲,主人公有千言萬語要向玩家訴說?;诂F(xiàn)在所掌握的知識,把每個字符用單引號括起來并放到數(shù)組中,那簡直就是噩夢!好在你的擔(dān)心是多余的,你發(fā)現(xiàn)的問題,語言的設(shè)計者已經(jīng)解決了,那就是使用char*指向常量字符串! 與單個字符賦值到數(shù)組相比,這種方式真的是輕松多了,而且也具有更好的可讀性。這個程序會完整的輸出"hello, world!",也不會出現(xiàn)亂碼。這就表明,以這種賦值方式保存的字符串,語言自身會在結(jié)束加上結(jié)束標(biāo)記。 這就是C風(fēng)格的字符串,以0結(jié)束。 在這種形式下,你可能想要嘗試修改一下某個字符,如hw[0]='a',程序可以編譯過去,但執(zhí)行會出錯。這是因為"hello, world!"是字面常量,確切的說是常量字符串,是不可修改的。(在古老的編譯環(huán)境下可能是正確的,如VC++6.0。另外,我們的聲明還可以更加精確一些,使用const chr *hw代替會更好一些,由于目前沒有學(xué)習(xí)const的意義,所以先不加;如果使用的是vs2017之類的編譯器,這里的聲明估計有問題。) 詳細(xì)的說,可以這么理解:想像一下,不管是變量還是常量,總要有能存儲這種東西的地方,這地方就是內(nèi)存,是內(nèi)存就有地址,對于常量存儲區(qū)域,具有不可寫標(biāo)記(即只讀)。hw僅是一個指針,指針的有效性就是指向一個地址,當(dāng)為hw賦值后它就指向了這個常量地址,因此編譯時是成功的。當(dāng)使用下標(biāo)修改時,系統(tǒng)發(fā)現(xiàn)你想要修改只讀內(nèi)存,然后被無情打臉。 你可能會抱怨,如果我真的想要修改字符串該怎么辦?1:把常量字符串轉(zhuǎn)換為數(shù)組。2:使用動態(tài)內(nèi)存分配。作為練習(xí),你可以基于現(xiàn)有的知識,嘗試按自己的思路去實現(xiàn)方法1。當(dāng)然,這些知識在后續(xù)的教程中也會一一道來。 |
|