error: assignment of read-only location の原因と直し方
const int *pのように「指す先が変更不可」なポインタを介して、*pに値を書き込もうとしたときに出るエラーです。
エラーメッセージの読み方
main.c:6:8: error: assignment of read-only location '*p'
main.c- ファイル名
6- 行番号
8- 列番号 — この位置でgccが構文解析に失敗しました
assignment of read-only location '*p'- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 int main(void) { 4 int y = 1; 5 const int *p = &y; 6 *p = 2; ^ 7 printf("%d\n", *p); 8 return 0; 9 }
const int *pは「指す先が読み取り専用」という意味です。値を変えたいときはポインタ経由ではなく、元の変数yを直接更新します。
直し方: *p を y にします。
パターン2
1 #include <stdio.h> 2 3 int main(void) { 4 int score = 10; 5 const int *ptr = &score; 6 *ptr = 20; ^ 7 printf("%d\n", *ptr); 8 return 0; 9 }
ptr自体を別のアドレスに向け直すことはできますが、指している先の値をptr経由で書き換えることはできません。
直し方: *ptr を score にします。
パターン3
1 #include <stdio.h> 2 3 int main(void) { 4 int temp = 36; 5 const int *reading = &temp; 6 *reading = 40; ^ 7 printf("%d\n", *reading); 8 return 0; 9 }
読み取り専用の指す先を書き換えようとすると、コンパイル時にエラーとして検出されます。
直し方: *reading を temp にします。
パターン4
1 #include <stdio.h> 2 3 int main(void) { 4 int z = 5; 5 const int *q = &z; 6 *q = 9; ^ 7 printf("%d\n", *q); 8 return 0; 9 }
const int *qは指す先が読み取り専用という意味です。値を変えたいときは元の変数zを直接更新します。
直し方: *q を z にします。
パターン5
1 #include <stdio.h> 2 3 int main(void) { 4 int level = 3; 5 const int *lp = &level; 6 *lp = 7; ^ 7 printf("%d\n", *lp); 8 return 0; 9 }
lp自体を別のアドレスに向け直すことはできますが、指している先の値をlp経由では書き換えられません。
直し方: *lp を level にします。
よくある誤解
const int *pはポインタ自体は変更できてもよく(別のアドレスを指し直せる)、指す先の値だけが読み取り専用になります。ポインタ自体を固定したい場合はint * const pという別の書き方が必要で、両者は意味が逆であることに注意が必要です。
実務での勘所
const int *pとint * const pのどちらが何を固定するのかを覚えるコツは、constの直前(すぐ左側)にある要素を修飾すると考えることです。const int *pは、constのすぐ左に何も無く直後がintなので「intの部分(指す先の値)」を修飾し、int * const pはconstのすぐ左に*があるので「ポインタ自体」を修飾します。両方を固定したい場合はconst int * const pのように両方の位置にconstを置きます。