C言語について質問があります。
1.
int **p;
const int **p1 = p; //型に互換性がないという警告
2.
int *p;
const int *p1 = p; //OK
上記2パターンありますが、なぜ1のパターンだと警告がでて、2のパターンだと警告が出ないのでしょうか?
コンパイラはgccの4系列と3系列で試してみましたが同じ結果になりました。
constで修飾されていても、変数の内容を変更できるかできないかだけで、型情報には影響を与えないと考えておりましたが、実際に警告がでてしまい、疑問に思っております
どなたか分かる人がいましたら教えていただけないでしょうか?
No.1
- 回答日時:
constは型の一部です。
ですので、int*と、const int*は異なる型です。
異なる型ですが、
「const型を指すポインタに非const型を指すポインタを代入できる」というルールがあるので、2のパターンは通るわけです。
ですので以下のような1の変形パターンはOKとなります。
int **p;
int * const * p1 = p;
なお、「const型を指すポインタのポインタに非const型を指すポインタのポインタを代入できる」というルールが無いのはなぜ?と聞かれると私には分かりません。なんででしょうね。
「const型を指すポインタに非const型を指すポインタを代入できる」
今回私が疑問に思っていたことがこの1文とjactaさんの返信で理解できました。
ありがとうございます。
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.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の回答の通りの理由で、変換することができません(警告ではなく、コンパイルエラーになります)。
ありがとうございます。
規格書を交えた説明は非常に分かりやすく納得できました。
次からは規格書にも目を通して考えて行きたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# 至急教えてください! プログラミングの問題です! お願いします! 出力2と全く同じ出力をするように、 2 2022/06/22 23:10
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# 変数のスコープ 5 2023/05/27 17:50
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# (C言語)めちゃくちゃな値になってしまいます。 5 2022/08/13 11:55
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
C言語の関数と配列に関する質問
-
fopne で失敗する原因
-
メモリのアドレスからの値の取...
-
init関数の意味
-
戻り値で構造体を返すことは可...
-
エラーの意味
-
参照型で受け取った引数をポイ...
-
【VC++2005(CLR)】マルチスレッ...
-
TCHAR文字列内の検索について
-
セグメントエラー
-
ポインタのアドレス範囲
-
【なぜポインタを使うのか】
-
C言語のプログラムをJavaに...
-
ポインタ変数の利用方法
-
コンストラクタでnewを失敗した...
-
クイックソートの比較交換回数...
-
ポインタのミスでOS壊れるの...
-
デバイスハンドルとは?
-
#define NULL ((void *)0) の弊害
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
C言語の関数と配列に関する質問
-
Run-Time Check Failure #3とい...
-
LPSTR型の初期化について
-
ExcelVBAでのkernel32(64bit)
-
main(int argc,char **argv[])...
-
アプリを32bitから64bit移行
-
ハンドルはポインタか
-
連結リスト 要素の入れ替え
-
C言語でのconstを返す関数
-
Cで作成したDLL関数をVBから呼...
-
NULLとブランクの違い
-
エラーの意味
-
ハンドル、アドレス、ポインタ...
-
DLL<->VB間での受け渡し(文字...
-
【C言語】戻り値が構造体の関数
おすすめ情報