- ベストアンサー
ポインタ宣言と初期設定について
- ポインタ宣言と初期設定についての説明です。C言語初心者向けの解説です。
- int *pt = &nn という記述は正しい書き方とされていますが、初学者にとっては分かりにくいと感じることがあります。左辺と右辺のデータ形式が異なるため、違和感を覚えることもあります。実際には int *pt; pt = &nn; という書き方と同じ意味です。
- ポインタ宣言と初期設定について、初学者が感じる疑問や違和感についての解説です。左辺と右辺のデータ形式の違いについても触れています。具体的な例文とともに理解を深めることができます。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
既に解決されたのかとも思いますが、少しだけ。 これは、「定義のときの形と、実際に使うときの形をなるべく同じにする」という発想がもとで、定義がわかりにくくなっているというものなのです。 その不自然さに気づくというのは、やはり、良いことだと思います。 さて、発想としては、 pt が int へのポインタであるとしたとき、*pt の型は int です。(これが使うときの形) だったら、*pt というのを、int で宣言すればいいよね(これが定義するときの形) というわけで、int *pt; で int へのポインタを宣言することになったのでした。 だから、構文的にも、 int a, b, *pt; (気持ちとしては、a や、b や、*pt の型が int) ということになっているわけです。 さて、初期化するときには、 (定義の形)= 初期値; という形にします。 ご質問の場合、初期値は &nn です。 一方「定義」は、 int *pt です。 これをくっつけて、(定義の形) = 初期値 にすると、 int *pt = &nn; のできあがり。 というわけです。
その他の回答 (3)
- acoronel
- ベストアンサー率50% (1/2)
int *pt; はint型のアドレスが入る変数(ポインタ)の定義です。 int i = 0; int *pt; (a) pt = &i; cout << *pt << endl; (b) とするとき (b) で0と出力されます。 ここで、(a) の*pt と (b) の *pt とは ”別物” であることは理解されているでしょうか? (a) では、int型のアドレスが入る変数(ポインタ)の宣言をしています。 (b) の *pt は、ポインタptが指すアドレスにある変数(ここでは i)を示します。 つまり、(a) と (b) とでは、同じ*記号を用いていても、意味することが違うのです。 > int *pt = &nn というのは、 > 左辺は「値」、右辺は「アドレス」という意味 から、左辺を上記の(b)と勘違いされているのではないでしょうか? 『int *pt = &nn;』 は、 『int型のアドレスが入る変数(ポインタ)ptの宣言 をしつつ、 ついでに、変数nnのアドレスを代入して初期化している』 と読めば、「気持ち悪さ」が取れると思います。
お礼
>『int型のアドレスが入る変数(ポインタ)ptの宣言 をしつつ、 ついでに、変数nnのアドレスを代入して初期化している』 おそらく、そうした理解が必要なんだろうとは思っていましたが、 参考書を読むだけでは確信が持てなかったため、質問をさせて頂きました。 おかげさまで、考え方が分かり、「気持ち悪さ」を払拭することが出来ました。 ありがとうございます。
- notnot
- ベストアンサー率47% (4900/10358)
センスとしては正しいと思います。 int *pt = &nn; のイコールは代入ではないので、左辺と右辺は代入のような関係ではないです。 int *pt は整数へのポインタ変数ptの宣言で、その変数の初期値が&nnということで、意味はお書きの通り、int *pt; pt=&nn; です。
お礼
>センスとしては正しい この言葉にとても救われました。 ありがとうございます。 これで混乱は解けました!
- kmee
- ベストアンサー率55% (1857/3366)
宣言の時は、int *pt は 「int * 型の変数 pt」 だと思ってください。 つまり、*はptにではなく、intの方に付くものだと。 文法上では、カンマで区切って複数書くときは int *p, *q ; と各変数の前に*が必要ですが、ここでは、*は「ポインタから実体を参照するための演算子」ではなく「ポインタであることを表す記号」だと考えましょう。あくまで、宣言しているのは「変数p」と「変数q」です。 「初期化」と「代入」は厳密には違います。
お礼
なるほど、そのように考えれば良いのですね。 何か大幅な理解ミスがあるのかと、不安に思っていましたが、 そうではないことが分かり、安心しました。 ただ単に、言語仕様がやや分かりにくい、ということだったのですね。 参考になりました。ありがとうございます。
お礼
回答、ありがとうございました。
補足
これまでの回答とはまた違った視点での回答でしたので、 大変興味深く読ませて頂きました。 これまでに頂いた回答を大別すると、 int *pt を どう分けて見るかで、分けられると思いました。 つまり、 (1)int * | pt (2)int | *pt の2通り。(※「|」で区切っている。) 回答NO.1の方は(1)、回答NO.4の方は(2)の考え方であると解釈しました。 結論から先に言うと、 「int *pt = &nn;」は、 「こう書くものなんだ、そのまま頭に入れておけ。そういう仕様だ。」 というのが、C言語利用者の暗黙の了解なのかもしれない、と思ったわけですが、 当初は、この書き方(ルール)に、 何かしらの合理的な理由があるのではないかと思っていました。 そして、いくつか回答を頂き、 私が想定していた「何かしらの合理的な理由」は、 明確に存在しているようでもなく、 「好きなように解釈し、覚えましょう(こじつけでも構いませんから)」 といった考え方で処理すべき事柄なのだと理解しました。 で、その考え方の1つとして、今回頂いた回答NO>4は、 私にとって、とても合点のいくものでした。 こちらの回答の考え方では、核となるものが2点あると感じました。 (1) *pt の型は int型 だから、「int *pt」と宣言するのは、 他の変数を宣言するときの方法と同じ書式と言え、その宣言方法には一貫性がある。 (2) 宣言と同時に初期化するときには、(定義の形)= 初期値; という形にする。 つまり、このルールに従うとすると、 『ポインタ』の宣言方法が「int *pt」というカタチに決まった上で、 その『ポインタ』の初期値を入れる初期化作業では、 右辺には『アドレス』データが来ることになります。 私の最初の理解も、漠然とではありますが、 おそらくこちらと同じ考え方だったと思います。 ただ、それで、はたして良いのだろうか?と思ったわけです。 (2)のルールは、やや強引な感じに思えなくもないですが、 そういうものなんだ、と考えれば、それ以上、悩むことはなさそうです。 実際、この質問で取り上げているポインタの宣言と初期化を同時に行うときの書式について、 「このような誤解し易いと思われる書式を採用したからには、 そのマイナス面をはねのけるだけの理由があるのではないか」 と思っていましたが、それはどうやらなさそうだ、と結論づけました。 と、ごちゃごちゃ書いてきましたが、 私のような違和感を感じる方は、実際、あまりいらっしゃらないのでしょうかね。 以上、駄文をお読み頂き、ありがとうございました。