1. 程式人生 > >C中常量字串和字元陣列的區別

C中常量字串和字元陣列的區別

1、 常量字串

在程式碼裡直接出現的”abcdef”這種字串,在程式執行的時候,系統會將它們放在常量區,所謂常量區就是一直存在的,只讀的,不可更改的資料區域,並且一個字串只會有一份。假設你在程式裡有兩行程式碼

char* p1 = “agcd”;

char* p2 = “agcd”;

無論你這兩個行程式碼隔了多遠,如果你想知道p1和p2所指向的字串在記憶體中是不是同一個,那答案是肯定的,p1和p2的值完全一樣。”agcd”這是一個存在於記憶體中的常量字串,它從程式一開始就在那裡,一直到程式結束都不會改變。在記憶體中,”agcd”是以如下方式儲存的

‘a’

’g’

‘c’

‘d’

‘\0’

它的最後肯定有一個字串結束標誌’\0’。這種字串的名字叫“以空字元為結束標誌的字串”。

char* p1 = “agcd”;

如果你這時候想改變第一個字元的值,用p[0] =’b’,系統會報一個錯,常量字元不能更改。(這裡為什麼指標可以當陣列用,下面再解釋)。

2、 字元陣列

如果你定義一個char a[10],那麼系統會“只分配”10個char這麼長的記憶體區域,一個char是一個位元組,那麼系統會分配十個位元組的記憶體空間,並且將這一片連續的記憶體空間的首地址賦值給a。也就是說“陣列名的值是陣列所在記憶體區域的首地址”換句話說“陣列名是一個指標,指向陣列第一個值的地址”。

如果你定義一個char a[] = “abcdefg”;這句程式碼就複雜點了。定義一個數組,陣列長度未知,那麼系統會根據等號後面的值來“初始化”這個陣列,等號後面是什麼?前面說過,它是一個常量字串。在記憶體中佔8個位元組,7個字元加上一個結束標誌。這時候在記憶體中就有兩個”abcdefg”的字串了,一個是常量區域的,另一個是根據前者複製了一份的。這句程式碼的意思就是複製一個常量區域的字串,將複製後的字串的首字母的地址賦值給a。

也就是說,最後a所指向的記憶體區域,已經不是常量裡的”abcdefg”了,這裡為什麼要複製一份呢?原因是因為常量是不允許更改的,而陣列一般都意味著需要修改,所以就複製了一份資料,放在非常量區域,就可以更改了。下面的測試程式可證明上述結論:

    char* p1 = "abcdef";

    char* p2 = "abcdef" ;

    char a[]= "abcdef" ;

    unsigned long dwP1 = (unsignedlong)p1 ;

    //32位系統裡的指標就是4個位元組的整數,這樣可以具體檢視指標的值。

    unsigned long

dwP2 = (unsignedlong)p2 ;

    unsigned long dwA = (unsignedlong)a ;

    printf("p1的值(32位地址)= 0x%X\n",dwP1);

    //%X是列印十六進位制,X是大寫,x是小寫

    printf("p2的值(32位地址)= 0x%X\n",dwP2);

    printf("a的值(32位地址) = 0x%X\n",dwA);

    執行後的截圖:

   

       從上面的結果可看出,常量字串在記憶體中只有一份。而賦值給陣列的時候,系統會拷貝一份。如果我們列印a[6]會是什麼結果呢,請注意,字串只有6個,最高索引是5。

      printf("a[6]的值=%d",a[6]);//以整數列印

    

雖然陣列的可用長度是6,但是它第7個位置還是存在的,那就是空字元結束標誌。空字元結束標誌是必須的,因為很多時候系統並不知道你的字串有多長。

3、 應用

當明白了這些本質後,我們怎麼來靈活使用字元陣列呢。在實際的編碼中,比如從檔案裡讀一段文字出來,假設當前檔案中的字串有20個字母。

第一步讀取檔案大小。

int fileSize = file.getSize();

第二步,分配快取。這是動態分配陣列。這種用法和java相似。

char* p = new char[fileSize+1] ;//1是為了後面放’\0’.

第三步,讀取

file.read(p,fileSize);//意思是從檔案裡讀取filesize個位元組,並且放在p所指向的快取中

第四步,標誌結尾

P[fileSize] = ‘\0’; //由於指標指向的是字串首字母地址,而陣列名也是一樣的,所以C/C++裡指標和陣列幾乎用法一樣。其他語言裡不一樣。這也是C/C++的魅力所在,夠靈活。

這時候的p所指向的就是一片連續的記憶體控制元件,它的內容就是檔案裡的字串,並且它的最後有一個結束標誌(這樣就可以在系統裡靈活使用了)