【C語言入門】170.指標與 const

今天這篇文章我們來討論指標和 const 之間一個微妙的關係。

Type * 可以轉成 const Type *

一個 type 的 pointer 可以轉型成一個 const Type 的 pointer。

char strA[] = "test";       
char *strB = "test";         
const char *strC = "test";

我們來分別看

char strA[] = "test"; 

把字串存成字元陣列,這個字元陣列大小是 5, 包含最後的”\0″。

char *strB = "test"; 

這是一個特例,我們把雙引號變成指標,指向字元陣列的第一個位置,字元陣列本身由編譯器產生。

唯讀,我們不能修改裡面的資料。

const char *strC = "test";

第三種,把她轉成 charater 的 pointer,不只是轉成字元的指標,我們在最前面還加了 const 來修飾這個字元。

const 也代表了指標指向的字元是唯讀的,是不能被修改的。

char strA[] = "test";       
char *strB = "test";         
const char *strC = "test";

strA[0]  = 'T';  // (O)
strB[0]  = 'T';  // (X) 未定義行為
strC[0]  = 'T';  // (X) 編譯失敗
strA[0]  = 'T'; 

我們真的有字元陣列存在,所以可以讀,也可以寫。

特性

可以分別改字元,但是沒辦法把整個陣列換掉。

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

strB 是個指標,指向的是系統產生的空間,字元陣列是唯讀的。

strC[0]  = 'T';  // (X) 編譯失敗

strC 在定義的時候約定是 const,因此不能被更改。如果試著更改會造成編譯失敗。

特性

不能改每個字元,但是可以把整個字串直接指向另一個字串。

因此在一般情況下,我們有兩個選擇:

  1. 和 strA 一樣,直接產生字元陣列去存字元。
  2. 和 strC 一樣,用 const char pointer 去存
char strA[] = "test";       
char *strB = "test";         
const char *strC = "test";

strA[0]  = 'T';  // (O)
strB[0]  = 'T';  // (X) 未定義行為
strC[0]  = 'T';  // (X) 編譯失敗

strA = strB;     //(char []) = (char *)  (X)
strA = strC;     //(char []) = (const char *) (X)
strA = strB;     //(char []) = (char *)  (X)

陣列不能直接被複製,因此不能放在等號的左邊。

strA = strC;     //(char []) = (const char *) (X)
strB = strA;     //(char *) = (char [])       (O)

字元陣列是可以存在指標的。這是因為字元陣列可以隱性轉型成字元的 pointer。

指標存的位置,剛好就是字元陣列中第一個位置。

strB = strC;     //(char *) = (const char *)  (X)

strC 指標裡存的是一個位置,這個位置所對應到的是一個字元,而這個字元是唯讀的,是不能被更改的。

strC = strA;     //(const char *) = (char [])  (O)

當我們把 strA 存到 strC 的時候,字元陣列會先轉型成字元的指標,也就是 character pointer,再把 character pointer 轉型成 const character pointer。

原本 strA 是可讀可寫,然後我們把他改成只能讀,因此是可行的。

strC = strB;     //(const char *) = (char *)    (O)

原本是可讀可寫,然後變成可讀。

char strA[] = "test";       
char *strB = "test";         
const char *strC = "test";

strA[0]  = 'T';  // (O)
strB[0]  = 'T';  // (X) 未定義行為
strC[0]  = 'T';  // (X) 編譯失敗

strA = strB;     //(char []) = (char *)        (X)
strA = strC;     //(char []) = (const char *)  (X)
strB = strA;     //(char *) = (char [])        (O)
strB = strC;     //(char *) = (const char *)   (X)
strC = strA;     //(const char *) = (char [])  (O)
strC = strB;     //(const char *) = (char *)   (O)

小結:

限制多的可以定義成 相對來說限制少的。

限制多的,例如 char *(可讀) ,限制少的,例如char [](可讀可寫)。

Leave a Comment

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