【C語言入門】167.字串字面常數的特殊性

在這篇文章,我們來介紹字串字面常數的特殊性。

所謂的字串字面常數,就是我們在上一篇文章介紹的雙引號所括住的字串的表示法(“test”)。

雙引號所括住的字串的表示法基本上可以作為一個字元陣列的初始化。

我們來看一下的例子。

char strA[] = "test";

strA 這個陣列會依序存放’t’, ‘e’, ‘s’, ‘t’ 以及一個字串結尾的 ‘\0’。

上一篇文章我們也提到,雙引號可以直接轉型成一個字元的指標。

char strA[] = "test";
char *strB = "test";   //字串字面常數可隱性轉型成字元指標

如果今天我們是用字元陣列的方式宣告定義的話,我們會宣告 5 個空間存字元。

如果今天我們是宣告一個字元指標的話,當我們透過這個指標,去存取 test 這個字串的時候,C 語言中的字串字面常數會儲存一個唯獨的空間.

裡面的 ‘t’, ‘e’, ‘s’, ‘t’, ‘\0’ 這 5 個空間是 C 語言的系統自動產生的,這 5 個資料是只能讀,不能寫的。

strA 本身是個陣列,有 5 個空間,每個空間存一個字元,舉個例子,我們可以直接存取第 0 號,也就是第 1 個格子,把裡面的字元改成大寫 T。

char strA[] = "test";
char *strB = "test";   //字串字面常數可隱性轉型成字元指標


strA[0] = 'T';  //(O)

但是如果今天我們通過 strB 這個指標,去存取它所指向的陣列的第一個元素,也就是 strB[0],它會從 strB 所指向的位址開始走 0 步取出一個字元變數,然後把這個字元變數設成大寫 T。

虛線中的是唯讀的,不能被修改的,因此 strB[0] = ‘T’ 其實是一種未定義行為。

因此,如果我們是把雙引號存在一個陣列的時候,由於我們有宣告定義這些格子,去儲存這些字元,所以我們能夠修改這些字元。

但如果我是宣告定義一個字元指標,直接存雙引號的位置的話,雙引號裡的字元,我並沒有去宣告定義房間來儲存。

儲存的空間是 C 語言自動產生的,因此我們只能去讀取,但不能修改。

如果更改的話就是未定義行為。

小結:

char strA[] = "test";
char *strB = "test";   //字串字面常數可隱性轉型成字元指標


strA[0] = 'T';  //(O)
strB[0] = 'T';  //(X) 未定義行為

strA 我宣告了 5 個記憶體空間去存字元,因此我們可以更改字元。

strB 只有宣告一個記憶體空間去存位置,因此不能被更改,一旦更改就是未定義行為。

我們再來看以下的例子。

strA = "Test"; //(X)編譯失敗
strB = "Test"; //(O)

陣列是不能直接被複製的,陣列變數是不能放在等號的左邊,但是雙引號可以直接轉成一個指標,複製給 strB。

雙引號大寫的 “Test” 會額外產生另一個空間,再新的空間同樣只能讀不能改。

換句話說,如果我們宣告的是字元陣列本身,我們可以改字元,但我不能整串換掉;但如果我宣告定義是指標本身,我們無法更改內容,但是我們可以通過重新定義來修改。

Leave a Comment

Your email address will not be published. Required fields are marked *