日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

小議char *和C語言的字符串...

 wangzai117 2006-04-27

作者:乾坤一笑

來源:http://blog./smileonce/archive/2005/06/26/8330.html

摘要:介紹了C語言中的char *和字符串,比較深入

前幾天和清風(fēng)雨交談strncpy()函數(shù)的時候,他認為“如果一個函數(shù)有一個char * str的參數(shù),那么str一定是一個字符串”,而我對此不以為然。難得到了周末,抽得出功夫,談?wù)勎覍har *含義的認識,與大家共同討論一下。

C語言是開發(fā)操作系統(tǒng)的首選語言,在很多方面都能從C代碼中看到機器的固有性質(zhì)。比如,PASCAL語言的數(shù)組索引是從1開始計數(shù),而C語言就是從0開始計數(shù)。從0開始計數(shù)不太符合一般人的正常思維模式,但是為什么C語言要采用這種設(shè)計方式呢?因為C語言最初主要是為操作系統(tǒng)開發(fā)人員和編譯器設(shè)計人員設(shè)計的——對于經(jīng)常需要考察內(nèi)存地址的開發(fā)人員,偏移量的概念在他們腦子里面根深蒂固。要把100個int型的整數(shù)放在從地址0x0000開始的一段內(nèi)存中,如果系統(tǒng)是按Byte編址的,那么第100個元素(其數(shù)組索引為99)的要放入的地址必然是:0x0000 + sizeof(int) * 99, 而不是乘以100,所以索引以0開始是很有好處的。(C語言的底層特性請參考P.V.D.L的《Expert C Programming——Deep C Secrets》,中文版《C專家編程》)

同樣而言,C語言對所謂字符串的處理也和其他語言不同。(參見拙著《我用錯了strcat() 》文后的評論) 它同樣體現(xiàn)了便于系統(tǒng)設(shè)計的特點。例如unix系統(tǒng)總是把設(shè)備都映射為文件,對I/O流、光驅(qū)、硬盤、modem的訪問最終都轉(zhuǎn)換為了對文件的處理。而文件,也可以看作是一個長長的字符數(shù)組(文件以EOF結(jié)尾)。C語言沒有專門定義字符串?dāng)?shù)據(jù)類型(如其他語言中的string),它用以‘\0‘結(jié)尾的字符數(shù)組來表示一個邏輯意義上的字符串。C語言用一些對于字符數(shù)組的處理函數(shù)(特別是對以‘\0‘結(jié)尾的字符數(shù)組的處理函數(shù))來處理所謂的以‘\0‘結(jié)尾的字符串,并把他們放在string.*、stdio.*等一些標準庫文件中。string這個字眼也就對人造成了某些誤解,好像是C語言中定義了字符串這種類型一樣。其實C語言只定義了char、int、float、void、poiner這幾種基本類型,這正是C語言簡潔之處。至于所謂的字符串,只是對字符數(shù)組的一種特殊應(yīng)用而已。

由于沒有了“字符串類型”,“傳char *參數(shù)就是傳一個字符串進來”之說自然也不攻自破。那么char *真正的含義是什么?我們不妨用大家最熟悉的int來對比一下。

#include <stdio.h>

int main(int argc, char *argv[])
{
int b[3] = { 17, 18, 19 };
int a = 5;
int d = 2103157716;
int * i; // pay attention to this variable(注意:這個指針 i)

i = b;
printf("%d \n", *i);  // i points to a array, *i gets the first number of the array, 
                          // i 是指向一個數(shù)組的 *i 是這個數(shù)組的第一個元素 // *i does not get the all elements of the array. (注: *i 不是指向所有的元素的)
i = b + 1; // okey, i can get whichever element of the array.
                        // 好了, i 得到了那個數(shù)組的第二個元素了(想想是不是呢)
printf("%d \n", *i); printf("Int size: %d \n", sizeof(int)); printf("Address0: %#x \n", i); // if i++, the value of i add by sizeof(int) i++; printf("Address1: %#x \n", i); i = &a; // i also can point to a int variable. as i is a pointer, we shoule printf("%d \n", *i); // use & to get the address of a. printf("%#x \n", d); // I use a big number to prove that int * is only a pointer, i = &d; // which is not tightness to int type. printf("%#x \n", *((unsigned char*)i)); return 0; }

代碼中的int * i就是我們關(guān)注的焦點。它是一個指向int指針。也就是說:i指向一個內(nèi)存地址,從這個地址開始存儲了一個數(shù)據(jù)。int * i中的int標明應(yīng)該使用int類型(長度為sizeof(int)個字節(jié))來從這個地址取數(shù)據(jù),也就是說要一次取sizeof(int)個byte的數(shù)據(jù)來拼成最后的結(jié)果。最后一個例子也證明了這一點:如果我們強制用unsigned char的大小的數(shù)據(jù)類型來對這個地址操作,就只能取出數(shù)據(jù)的一部分。反過來說,如果用較大數(shù)據(jù)類型來取實際存儲較小數(shù)據(jù)類型的數(shù)據(jù),就有可能越界操作內(nèi)存,取回一些雜亂的內(nèi)容或?qū)е孪到y(tǒng)崩潰。int b[]這個數(shù)組,標明有一組數(shù),放在以&b開始地址的內(nèi)存空間內(nèi),每個元素占用了sizeof(int)個byte的內(nèi)存單元;如果有類似于i=&b;i++;的操作,i的值就每次遞增sizeof(int)而不是1,這樣確保了i每次都能恰好取回一個正確的int。

同理,char * c也是如此。如果我們定義了一個char *的變量c,那么c也只不過是一個指向內(nèi)存中某個地址的指針而已。之所以標明它是char *的類型,就是說要以sizeof(char)為單位去內(nèi)存中取數(shù)。所以,我們應(yīng)該稱呼char * c為指向char類型的指針——而不是說c就是字符串。為什么傳一個char *指針給printf(),strlen()之類的函數(shù),它就能把它當(dāng)作一個字符串來處理呢?沒錯,我們不是定義了‘\0‘來表示一個"字符串"的終結(jié)么?我們只需從起始地址不斷累加,遍歷字符數(shù)組的每一個元素,直到找到一個‘\0‘為止,就算是處理一個字符串了——從起始地址到‘\0‘為止的字符數(shù)組元素構(gòu)成一個“字符串”,這就是C語言設(shè)計字符串的原理。

所以,當(dāng)一個函數(shù)要求傳入一個char *的參數(shù),并不一定這個參數(shù)就一定是字符串(以‘\0‘結(jié)尾的字符數(shù)組),char *只是一個字符指針而已,它僅僅提供了一個內(nèi)存地址和每次遍歷元素的偏移量而已。究竟函數(shù)對傳入的參數(shù)有什么要求,還要視函數(shù)的具體實現(xiàn)而定。(我想ANSI C應(yīng)該對參數(shù)有所要求和規(guī)定,可惜偶沒有ANSI C文件,無法參考。 )C語言一般約定是用char * str來表示以‘\0‘結(jié)尾的字符數(shù)組,但是由于某些實現(xiàn)上的效率的考慮,往往沒有嚴格遵守這個約定。C語言的設(shè)計理念中沒有強調(diào)使用者一定要使用遵守這個約定,不遵守這個約定也不違背C語言的基本語法規(guī)則。這或許可以看作是C語言和創(chuàng)造和使用它的黑客群體崇尚自由的一種特色、一種精神文化吧。


小練習(xí):
1)參照上面int *的例子來編寫一個類似代碼驗證一下char *是否也有類似特性。
2)C語言這么設(shè)計字符串會在那些方面的處理上有為難之處。
3)考察C語言標準庫函數(shù)中,有那些函數(shù)傳入char*的參數(shù)是一定要求以‘\0‘結(jié)尾的,那些函數(shù)對char *參數(shù)不做這個檢查。

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=670277

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多