簡單討論C中的字元陣列相關的問題
1.字元陣列跟字元指標有什麼區別?
首先我們知道,定義一個字元陣列如下:
char arr[ ]= "abbbbbcdfefedfadsf"
定義一個字元指標如下:
char* p2 ="abbbbbcdfefedfadsf";
眨眼一看,感覺確實沒什麼區別,但我想說的是區別很大。
我們先來了解一下記憶體的大概儲存是如何分佈的:
圖一:記憶體的大致分佈
假設,陣列跟指標都在main函式中定義,從這個圖可以看出陣列跟指標都是在棧區開闢空間,因為他們都是區域性變數;
好,那麼我們從知道了他們都在棧區開始,來開始解答為什麼區別很大
(1)從初始化角度看是一樣的,都是給他們初始賦值成"abbbbbcdfefedfadsf";這個賦值的字串儲存的空間可不是都在棧區。
char arr[ ]= "abbbbbcdfefedfadsf";
char* p2 ="abbbbbcdfefedfadsf";
arr[ ]中的字串是一種備份,而指標存入的是字串的地址;
備份跟地址後面再說,先埋個伏筆。
(2)字元陣列跟字元指標的功能不同。
你在用char arr[]的時候,雖然不能用arr直接賦值字串,即 arr = “hello world”;但你可以用arr[ i ],i∈(0~(arr元素個數 - 1)),來改變arr陣列的值;
而字元指標的本質就是指向了一個記憶體空間,只要是有權可以訪問,指標就可以指向該記憶體區域並修改這個區域的值,所以說指標真的不能亂用好吧。
(3)最後來說說,備份跟地址的事。
假設定義int arr[ 10 ] = { 0 };
陣列儲存的時候,其實是在棧區開闢了一塊連續的儲存空間;第一個元素arr[ 0 ]為最低的地址,每次地址+1時,依次訪問後面的元素,當地址+9時,訪問的元素就是arr[ 9 ]。而初始化為0,其實就是把arr[ 0 ] = 0;arr[ 1 ] = 0;......arr[ 9 ] = 0。這就是所謂的備份;
那麼在char arr[ ]= "abbbbbcdfefedfadsf" 這句當中,實際就是把每個字元給到對應元素中,最後一個元素就是放了‘\0’表示字串結束,當你除錯VS或者VC的時候,就可以看到arr[ 0 ] = ‘a’;arr[ 0 ] = ‘b’;......arr[ 18 ] = ‘\0’;
圖二:陣列的各個元素情況
因為這是對最初版本(就是"abbbbbcdfefedfadsf")的copy,那肯定是可以改的,所以要對某字串進行修改可以採用字元陣列寫法;
那指標可以嗎?如果你要修改它所指向的字串,我們就試試吧。
圖三:程式掛了
好傢伙,程式直接崩了。
那現在我們可以知道定義char* p1 ="abbbbbcdfefedfadsf";p1實際上是不可變的,那這個原因我想大家應該看了最上面的圖一就知道了,一般來說p1指向的是一塊空間,而你單寫一段字串,像"abbbbbcdfefedfadsf",系統會將這個字串儲存到程式碼段裡,這個程式碼段可牛了,儲存的是一種常量,是不可修改的,固定的值。p1指向了不可修改的空間,你要去改它的值,那當然不行。所以我們一般寫這種程式碼,最好寫成 const char* p1 = "abbbbbcdfefedfadsf"; 前面的const是修飾*p1整體,表示不可修改p1所指向的值。
2.這兩者定義有何區別?
char arr1 [ ] = "abcd" ①
char arr2 [ ] = {‘a’,‘b’,‘c’,‘d’ } ②
我們在VS19run一下
結果很明顯了,arr2實際就只有4個元素,剛開始學習的時候很多小夥伴都是認為這兩種沒什麼區別,結果就導致了一些bug的出現,在以後寫程式碼時,要避免這種小錯誤;
最後,總結一下
(1)char* p1 ="abbbbbcdfefedfadsf";寫法不嚴謹,最好寫成 const char* p1 = "abbbbbcdfefedfadsf";
(2)如果要修改字串裡的值,寫成字元陣列形式,一般是在函式傳參時,需要特別注意;
(3)char arr1 [ ] = "abcd" ,char arr2 [ ] = {‘a’,‘b’,‘c’,‘d’} 兩種寫法並不等價;