- ベストアンサー
C言語におけるポインターとconstの関係について
C言語について質問があります。 1. int **p; const int **p1 = p; //型に互換性がないという警告 2. int *p; const int *p1 = p; //OK 上記2パターンありますが、なぜ1のパターンだと警告がでて、2のパターンだと警告が出ないのでしょうか? コンパイラはgccの4系列と3系列で試してみましたが同じ結果になりました。 constで修飾されていても、変数の内容を変更できるかできないかだけで、型情報には影響を与えないと考えておりましたが、実際に警告がでてしまい、疑問に思っております どなたか分かる人がいましたら教えていただけないでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
JIS X3010の6.3.2.3 ポインタには、次のように記述されています。 「任意の型修飾子qに対して非q修飾型へのポインタは, その型のq修飾版へのポインタに型変換してもよい。」 また、次のようにも記述されています。 「オブジェクト型又は不完全型へのポインタは, 他のオブジェクト型又は不完全型へのポインタに型変換できる。」 何か微妙な記述ですが、型T*から型q T*へは変換できるが、型q T*から型T*への変換は明言を避けています。ただし、後者の記述によって、関数型以外へのポインタ同士の相互変換はできるとなっていますから、型q T*から型T*への変換できないわけではありません。 また、前者の記述は、あくまでも型T*から型q T*への変換のことであって、型T**から型q T**への変換のことではありません。型T**は、(T*)*というイメージですし、型q T**なら(q T*)*というイメージだからです。 型q T*から型T*への変換にせよ、型T**から型q T**への変換にせよ、後者の記述にある「オブジェクト型又は不完全型へのポインタ」ですから、相互変換は可能です。その辺の微妙なところを指摘するために警告が出ているものと思われます。 警告というのは、規格が定めるものではなく、処理系が勝手に出しているものですから、その真意を知るには、処理系の設計者に聞くしかないと思いますが、まあ、この解釈で当たらずとも遠からずかと思います。 ちなみに、C++の場合には#3の回答の通りの理由で、変換することができません(警告ではなく、コンパイルエラーになります)。
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
#2 です. cppll で調べました. int ** から const int ** に変換できるとすると, 次の場合に破綻するみたい: int *pi; const int **ppci = π const int ci = 0; *ppci = &ci; *pi = 1; これで const なはずの ci の値が pi 経由で変更できます.
お礼
ありがとうございます。 これはなかなかやろうとは思いませんが、危険ですね。 参考になりました。 cppllはC++の話がメインのようですが、機会があれば目を通していきたいと思います。
- Tacosan
- ベストアンサー率23% (3656/15482)
よく覚えていないんだけど, 確か 1 のパターンを許すと const にからんで危険なことができちゃったはず. const が合法的に外せるんだっけ....
- MASATO3
- ベストアンサー率60% (27/45)
constは型の一部です。ですので、 int*と、const int*は異なる型です。 異なる型ですが、 「const型を指すポインタに非const型を指すポインタを代入できる」というルールがあるので、2のパターンは通るわけです。 ですので以下のような1の変形パターンはOKとなります。 int **p; int * const * p1 = p; なお、「const型を指すポインタのポインタに非const型を指すポインタのポインタを代入できる」というルールが無いのはなぜ?と聞かれると私には分かりません。なんででしょうね。
お礼
「const型を指すポインタに非const型を指すポインタを代入できる」 今回私が疑問に思っていたことがこの1文とjactaさんの返信で理解できました。 ありがとうございます。
お礼
ありがとうございます。 規格書を交えた説明は非常に分かりやすく納得できました。 次からは規格書にも目を通して考えて行きたいと思います。