char a[](字串陣列)和char *a(字串指標)區別
在C語言中,對字串的操作主要有兩種方式,一是使用字元陣列,char str[];二是使用字元指標。那麼二者有什麼區別呢?下面將分述二者的使用,最後進行比較。
一、字元陣列
使用char str[]定義一個字元陣列str,中括號內可以寫上數字表示陣列大小,也可以不寫。如果不寫數字,則必須為字元陣列提供初始值,以便編譯器進行記憶體分配。
可以使用字串字面值(string literal)來初始化字元陣列,也可使用字元字面值(character literal)初始化,如:
[cpp] view plain copy print?-
char str1[10]=
- char str2[]="World";
- char str3[]={'H','e','l','l','o'};
只能對字元陣列元素的賦值,而不能用賦值語句對整個陣列賦值,如: [cpp] view plain copy print?
- char str4[10];
- str4={'H','e','l','l','o'}; // 錯誤
- str4="Hello"; // 錯誤
- str4[0]='H';str4[1]='e';str4[2]='l';str4[3]='l';str4[4]='o'; // 正確
可以使用迴圈將字元陣列中的字元一個一個輸出,也可以使用cout<<str1直接輸出整個陣列。
需要注意的是,上述程式碼中str1和str2是C風格字串,而str3不是。C風格字串,是指以\0結尾的字元陣列。C++為了相容C,而保留了C中字串的使用方法。
str1和str2使用字串字面值進行初始化,字串字面值使用\0表示字串結束。因此str2長度為6,需要將\0計算在內。使用strlen函式,計算的是字串的實際長度,不包含\0。
而str3則不一樣,它沒有\0作為結束標誌,因而不是C風格字串,使用cout<<str3可能會出現意想不到的結果。
二、字元指標
可以使用char *str指向一個字串。如:
[cpp] view plain copy print- char *ptr="C++";
- char strArr[]="C++";
- char *ptr2=strArr;
使用cout<<ptr即可輸出整個字串,而使用cout<<*ptr則輸出字串的首字元。
字元指標也可指向C風格字串,如ptr就是指向的C風格字串。如果讓ptr指向上節中的str3,輸出ptr會出現同樣的意想不到的結果。畢竟陣列名其實就是一種指標。
三、區別
前面簡單介紹了一下兩種操作字串的方法,這部分進行比較,是本文的重點。如下程式碼:
[cpp] view plain copy print?- char s[]="abc";
- char *ptr="abc";
- cout<<s<<endl; // abc
- cout<<*s<<endl; // a
- cout<<&s<<endl; // 地址
- cout<<(s+1)<<endl; // bc
- cout<<*(s+1)<<endl; // b
- cout<<&s[1]<<endl<<endl; // a
- cout<<ptr<<endl; // abc
- cout<<*ptr<<endl; // a
- cout<<&ptr<<endl; // 地址
- cout<<(ptr+1)<<endl; // bc
- cout<<*(ptr+1)<<endl; // b
- cout<<&ptr[1]<<endl; // a
下面說二者的不同之處。如下一段程式碼:
[cpp] view plain copy print?- char ss[]="C++";
- ss[0]='c'; // 合法
- char *p="C++";
- p[0]='c'; // 合法但不正確
原因在於兩種方式對字元陣列操作的機制不同。使用char *p="C++"語句後,編譯器在記憶體的文字常量區分配一塊記憶體,儲存”C++“這一字串字面值,然後在棧上分配記憶體儲存p,p的內容為"C++"的地址。p[0]='c'試圖修改常量”C++“,程式當然就會崩潰了。而char ss[]="C++"語句,定義了一個數組,編譯器為其在棧上分配了記憶體空間,因而可以進行修改操作。
因此,可以總結如下:
(1)char ss[]定義了一個數組,ss可認為是一個常指標,ss不可改變,但ss指向的內容可以發生改變。
(2)char *p定義了一個可變指標,p可以指向其它物件。但對於char *p=”abc“這樣的情況,p指向的是常量,故內容不能改變。
如下程式碼進一步說明char ss[]和char *p的區別:
[cpp] view plain copy print?- char *strA()
- {
- char str[]="Hello";
- return str;
- }
呼叫該函式,不一定能夠得到正確的結果。因為str定義了一個區域性資料,是區域性變數,存在於函式strA中的棧幀中。當函式呼叫完成後,棧幀恢復到函式strA呼叫前的狀態,臨時空間被重置,為函式分配的棧空間被收回,str所指向的地址也就不存在了。
將上述程式碼修改:
[cpp] view plain copy print?- char *strA()
- {
- char *str="Hello";
- return str;
- }
該函式能夠正常執行,因為str指向的字串字面值被儲存在只讀的資料段,是全域性的,當函式呼叫完成後,str指向的地址未發生變化。
綜上,可以看出使用char []較容易出錯,可能出現不確定的結果。C++提供的string類相比之下,要安全的多了。