C言語について質問があります。
1.
int **p;
const int **p1 = p; //型に互換性がないという警告
2.
int *p;
const int *p1 = p; //OK
上記2パターンありますが、なぜ1のパターンだと警告がでて、2のパターンだと警告が出ないのでしょうか?
コンパイラはgccの4系列と3系列で試してみましたが同じ結果になりました。
constで修飾されていても、変数の内容を変更できるかできないかだけで、型情報には影響を与えないと考えておりましたが、実際に警告がでてしまい、疑問に思っております
どなたか分かる人がいましたら教えていただけないでしょうか?
No.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の回答の通りの理由で、変換することができません(警告ではなく、コンパイルエラーになります)。
ありがとうございます。
規格書を交えた説明は非常に分かりやすく納得できました。
次からは規格書にも目を通して考えて行きたいと思います。
No.3
- 回答日時:
#2 です. cppll で調べました. int ** から const int ** に変換できるとすると, 次の場合に破綻するみたい:
int *pi;
const int **ppci = π
const int ci = 0;
*ppci = &ci;
*pi = 1;
これで const なはずの ci の値が pi 経由で変更できます.
ありがとうございます。
これはなかなかやろうとは思いませんが、危険ですね。
参考になりました。
cppllはC++の話がメインのようですが、機会があれば目を通していきたいと思います。
No.1
- 回答日時:
constは型の一部です。
ですので、int*と、const int*は異なる型です。
異なる型ですが、
「const型を指すポインタに非const型を指すポインタを代入できる」というルールがあるので、2のパターンは通るわけです。
ですので以下のような1の変形パターンはOKとなります。
int **p;
int * const * p1 = p;
なお、「const型を指すポインタのポインタに非const型を指すポインタのポインタを代入できる」というルールが無いのはなぜ?と聞かれると私には分かりません。なんででしょうね。
「const型を指すポインタに非const型を指すポインタを代入できる」
今回私が疑問に思っていたことがこの1文とjactaさんの返信で理解できました。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
戻り値で構造体を返すことは可...
-
LPSTR型の初期化について
-
C言語でのconstを返す関数
-
init関数の意味
-
関数ポインタの高速化のメリット
-
ハンドル、アドレス、ポインタ...
-
参照型で受け取った引数をポイ...
-
C言語のポインタに直接アドレス...
-
リスト構造
-
Wordでのリンク方法(Ctrlキー...
-
キャストについて str = (CStr...
-
B-reps(境界表現)をC、C++で...
-
ハンガリアン記法は廃れた?
-
お薦めの本(明解C言語初級を...
-
CreateWindowWithLogonW関数が...
-
fopne で失敗する原因
-
^と*の違いについて
-
_TCHAR、LPCWSTRについて
-
TCHAR文字列内の検索について
-
PASCALとFARの意味
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
セグメントエラー
-
fopne で失敗する原因
-
戻り値で構造体を返すことは可...
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
C言語でのconstを返す関数
-
ハンドルはポインタか
-
【C言語】戻り値が構造体の関数
-
nullポインタを逆参照とは?
-
基本アルゴリズムの『返す』の...
-
参照型で受け取った引数をポイ...
-
#define NULL ((void *)0) の弊害
-
アプリを32bitから64bit移行
-
ハンドル、アドレス、ポインタ...
-
デバイスハンドルとは?
-
C++で関数ポインタから関数名を...
-
Cで作成したDLL関数をVBから呼...
おすすめ情報