const與指標

以下二種十分容易混淆,而且十分難記。

Pointer to Const (const*)

const右邊是星號*

const保護的是指標位址中的內容,被const保護的地方代表只能讀取,不能修改。

下圖中,const保護的是0x1000記憶體位址的內容不被修改。
img

無法使用*取值運算子修改指標的內容。

*指標 = 修改的內容
1
2
3
4
5
6
7
8
9
10
11
12
int main() {
  int var1 = 10;
  //將var1的位址給指標變數p
  int const * p = &var1;

  //p指標位址中的內容是常數,常數不能修改,所以不能使用*指標 = 修改的內容
  //* p = 11;
  
  //印出var1的值與p指標位址中的值
  cout << "var1=" << var1 << ",p=" << * p << endl;
  return 0;
}
執行結果
var1=10,p=10

int const * p可以更改成const int* p,二者為一樣的意思,只要記得const右邊若先出現星號*而不是變數名,代表指標位址中的內容是唯讀,無法修改。

1
2
3
4
5
6
int main() {
  int var1 = 10;
  const int* p = &var1;
  cout << "var1=" << var1 << ",p=" << * p << endl;
  return 0;
}

第3行,int const * p可以更改成const int* p

可以修改指標指向的記憶體位址

1
2
3
4
5
6
7
8
9
10
11
int main() {
  int var1 = 10;
  int var2 = 20;
  //將var1的位址給指標p
  const int* p = &var1;
  cout << "var1=" << var1 << ",p=" << * p << endl;
  //將var2的位址給指標p
  p = &var2;
  cout << "var2=" << var2 << ",p=" << * p << endl;
  return 0;
}
執行結果
var1=10,p=10
var2=20,p=20

const字串指標

Prerequisites:

char *c = "字串內容"

「c指標」指向RODATA區塊的字串「常數」,RODATA是唯讀區塊,無法修改字串常數的內容,但可以修改指標指向到新的字串常數。。

img

字串指標加上const

因為指向的RODATA已經是字串「常數」,建議在char* 前加上const常數宣告,編譯器才不會出現警告,字串指標加上const代表無法修改RODATA的字元,但可以指向其它常數字串。

下面程式碼,加上const無法修改"abc"常數字串,指標名c,可以指向其它新的常數字串。

1
2
3
4
5
int main() {
  const char* c = "abc";
  printf("%s \n",c);
  return 0;
}

RODATA區塊的字串常數無法修改。
以下會編譯錯誤。

1
2
3
4
5
6
int main() {
  const char* c = "abc";
  c[1] = g;
  printf("%s \n",c);
  return 0;
}

指標可以指向其它字串。

1
2
3
4
5
6
int main() {
  const char* c = "abc";
  c = "zzzz";
  printf("%s \n",c);
  return 0;
}
zzz

Const Pointer (const 指標變數)

const右邊是指標變數

指標類型* const 指標變數 = 記憶體位址
1
int* const p = &i;

下圖中,const保護的是指標存的記憶體位址不被修改。
p變數的記憶體位址0x1008,儲存的0x1000的記憶體位址,要保護的是儲存的0x1000,不被修改成其它記憶體位址。
img

使用const修飾指標變數,代表指標不能再指向其它記憶體位址。
使用const修飾指標變數,要初始化記憶體位址,以下編譯失敗,沒有指派記憶體位址給p。

1
2
3
4
5
int main() {
  int i = 10;
  int* const p;
  return 0;
}

不能再更改指標指向的記憶體位址。

1
2
3
4
5
6
7
8
9
10
11
int main() {
  int var1 = 10;
  int var2 = 11;
  //const右邊是指標名p,初始化要指派記憶體位址,不能是nullptr
  int* const p = &var1;

  //將var2的位址給指標p,會編譯失敗,不能被修改位址。
  //p = &var2;
  cout << "var1=" << var1 << ",p=" << *p << endl;
  return 0;
}

可以修改內容

不能修改指標的記憶體位址,但可以修改記憶體位址的內容。

可使用*取值運算子修改記憶體位址的內容。

*指標 = 修改的內容
1
2
3
4
5
6
7
8
int main() {
  int var1 = 10;
  int* const p = &var1;
  // 可以修改位址中的內容
  * p = 55;
  cout << "var1=" << var1 << ",p=" << * p << endl;
  return 0;
}
執行結果
var1=55,p=55

results matching ""

    No results matching ""