質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

2426閲覧

constとポインタの関係

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/08/20 09:23

編集2018/08/20 09:47

参考書でconstポインタなるものを見てどのような仕組み
なんだと手当たり探ってみましたが、いまいち理解できません
わかる方いましたら、constポインタの使用理由・方法教えてほしいです
よろしくお願いします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2018/08/20 09:27

質問内容に関係がなく恐縮ですが、前から気になっていたので。なぜ見出しを不必要に多用するのでしょうか?
退会済みユーザー

退会済みユーザー

2018/08/20 09:41

見やすいからです
LouiS0616

2018/08/20 09:46

大きい文字の方が読みやすい人はブラウザ側で文字サイズを変更できるので、本来別の役割を持つ機能を濫用しない方が良いと思うのですが。
退会済みユーザー

退会済みユーザー

2018/08/20 09:47

わかりやした
guest

回答3

0

ベストアンサー

constポインタなるものを見てどのような仕組みなんだと

ポインタ自体、或いは生成された機械語自体に、特別な「仕組み」があるのではなく、書き変えてはいけない・書き変えられない場所、READ-ONLYな場所を、プログラムが書き変えようとしていたら、コンパイルエラーとして検出できる事が仕組みに相当すると思います。コンパイルが通らなければ、やっちゃいけないこと・危険なことを実行しないで済みますから。

なので、プログラムのミスを減らし、安全性を担保することが存在理由だと思います。const が適切に使われているプログラムは信頼性が高いだろう、というわけです。

そのためには、書き変えてはいけない・READ-ONLYな場所を、適切に指定することが肝心です。cateyeさんのお答えと同じですが、書き変えられない場所に注目して書き直すと

  • const char *ptr; は、ポインタが指すメモリを書き変えない ←最もよく使う形
  • char * const ptr; は、ポインタ自体を変更しない。一箇所を指したまま
  • const char * const ptr; は、ポインタが指す先も、ポインタも変更しない
  • ただの char *ptr; なら、ポインタが指す先も、ポインタ自体も変更できる

ダブルポインタ(ポインタへのポインタ)の場合、const を考えなければ

C

1 char **ptr = ???;

ですが、この場合 const を書ける場所が3箇所あります。普通こんな書き方しないけど、3箇所全てに const を書くとこんな感じ。

C

1   const char * const * const ptr = ???;

どの const が、どこをREAD-ONLYにするか、手を動かして調べてみたら良いと思います。

投稿2018/08/21 05:21

編集2018/08/21 05:26
rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/21 12:20

丁寧な解説ありがとうございます
guest

0

const ポインタの存在理由

ポインタというのは「メモリ上のデータがある位置」を差し示すものですが、これを教えるというのはそれなりのリスクを伴います。というのは、原理的に、この情報を使えばデータそのものを書き換えられてしまうからです。つまりポインタを使うときは、ポインタを渡す関数がデータを破壊しないと信用するか、あるいは「このポインタ経由ではデータを書き換えられない」ようにする仕組みが必要です。後者の仕組みが const ポインタです。 const 修飾されたポインタは、そのポインタを経由して、指し示す先のデータを書き換えることはできません。しようとしたときにコンパイラが怒ってくれます。

まあ const ポインタを強引に突破することもできてしまうので、どちらかというと関数が引数でポインタを必要とするときに「私はこのポインタの指し示す先を書き換えませんよ」ということをアピールする意味合いが強いです。

const ポインタの使い方

(変な例ですが) たとえば次のような関数を考えてみます。引数として与えられたポインタ a, b の指し示す先の値を足す関数 add() です。

c

1int add(int *a, int *b) { 2 return *a + *b; 3} 4 5int main(void) { 6 int a = 3, b = 4; 7 printf("%d\n", add(&a, &b)); // 3 + 4 を計算して 7 を表示してほしい。 8 return 0; 9}

さて、この関数はポインタを受け取っているので、その気になれば値を書き換えられてしまいます。
ただ足し算をするだけの関数のフリをして、渡された値を変えてしまうことができます。

c

1int add(int *a, int *b) { 2 *a = 10; // 書き換えられてしまう 3 return *a + *b; 4} 5 6int main(void) { 7 int a = 3, b = 4; 8 printf("%d\n", add(&a, &b)); // 3 + 4 を計算して 7 を表示してほしい。 9 // しかし add() の中で a の中身を書き換えられてしまったので変な答え (14) が表示される。 10 // しかもこれ以降 a の値が 10 になっている! 11 if (a == 3) { 12 // 結果として a != 3 なので、この非常に大事な処理は実行されない。 13 very_important_work(); 14 } 15 return 0; 16}

結果として、本来実行されるべき very_important_work() が実行されなくなりました。バグの完成です。ポインタを要求されると使う側はこんなことをされないか心配しないといけません (そしてデバッグが面倒になります) 。逆に真っ当な add() 関数を作る側からしても、使う人に余計な心配をさせてしまうのは本意ではありません。

ということで、この関数はそういう書き換えをしませんよというアピールとして、 const をつけるのです。

c

1int add(int const *a, int const *b) { 2 // *a = 10; // 今度は書き換えようとするとエラーになる。 3 return *a + *b; 4} 5 6int main(void) { 7 int a = 3, b = 4; 8 printf("%d\n", add(&a, &b)); // 3 + 4 を計算して 7 を表示してほしい。 9 if (a == 3) { 10 // a は書き換えられないので、最初の値を保っているはず。 11 very_important_work(); 12 } 13 return 0; 14}

ちなみに、 const ポインタを通常のポインタに渡すことはできません (書き換えない!と宣言して受け取ったポインタを、書き換え可能なポインタとして渡すことは当然できません) 。ということは、中身を書き換えない関数なのに const を付けなかったせいで、 const ポインタを受け取っている他の関数から呼び出せなくなったりします。

c

1// a をただ表示するだけの、書き換えない関数。 2// 書き換えないけど a は const ポインタになっていない 3void do_subtask(int *a) { 4 printf("%d\n", *a); 5} 6 7// 書き換えられない a を受け取る関数 8void do_task(int const *a) { 9 // do_subtask() は「結果的に」内容を書き換えないが、 10 // 引数が const になっていないので渡せない。 11 // do_subtask(a); // ← コンパイルエラー 12} 13 14int main(void) { 15 int a = 3; 16 do_task(&a); 17 return 0; 18}

自分の作った関数が他の関数から呼び出される可能性を考えても、指し示す先を書き換えないポインタ引数には常に const をつけるべきです。

投稿2018/08/20 10:28

Eki

総合スコア429

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/21 12:21

わかりました ありがとうございます
guest

0

ちょっと難しいですよね・・・合ってるかなぁ^^;
const char * ptr; // ポインタの変更が可能
char * const ptr; // ポインタの変更が不可
const char * const ptr; // すべて変更不可

参考:意外に知らないconst修飾子の使い方

投稿2018/08/20 10:10

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/08/21 12:21

なるほどですね ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問