• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:ポインタ宣言と初期設定の書き方について)

ポインタ宣言と初期設定について

このQ&Aのポイント
  • ポインタ宣言と初期設定についての説明です。C言語初心者向けの解説です。
  • int *pt = &nn という記述は正しい書き方とされていますが、初学者にとっては分かりにくいと感じることがあります。左辺と右辺のデータ形式が異なるため、違和感を覚えることもあります。実際には int *pt; pt = &nn; という書き方と同じ意味です。
  • ポインタ宣言と初期設定について、初学者が感じる疑問や違和感についての解説です。左辺と右辺のデータ形式の違いについても触れています。具体的な例文とともに理解を深めることができます。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

既に解決されたのかとも思いますが、少しだけ。 これは、「定義のときの形と、実際に使うときの形をなるべく同じにする」という発想がもとで、定義がわかりにくくなっているというものなのです。 その不自然さに気づくというのは、やはり、良いことだと思います。 さて、発想としては、 pt が int へのポインタであるとしたとき、*pt の型は int です。(これが使うときの形) だったら、*pt というのを、int で宣言すればいいよね(これが定義するときの形) というわけで、int *pt; で int へのポインタを宣言することになったのでした。 だから、構文的にも、 int a, b, *pt; (気持ちとしては、a や、b や、*pt の型が int) ということになっているわけです。 さて、初期化するときには、 (定義の形)= 初期値; という形にします。 ご質問の場合、初期値は &nn です。 一方「定義」は、 int *pt です。 これをくっつけて、(定義の形) = 初期値 にすると、 int *pt = &nn; のできあがり。 というわけです。

nbsp0606
質問者

お礼

回答、ありがとうございました。

nbsp0606
質問者

補足

これまでの回答とはまた違った視点での回答でしたので、 大変興味深く読ませて頂きました。 これまでに頂いた回答を大別すると、 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)のルールは、やや強引な感じに思えなくもないですが、 そういうものなんだ、と考えれば、それ以上、悩むことはなさそうです。 実際、この質問で取り上げているポインタの宣言と初期化を同時に行うときの書式について、 「このような誤解し易いと思われる書式を採用したからには、 そのマイナス面をはねのけるだけの理由があるのではないか」 と思っていましたが、それはどうやらなさそうだ、と結論づけました。 と、ごちゃごちゃ書いてきましたが、 私のような違和感を感じる方は、実際、あまりいらっしゃらないのでしょうかね。 以上、駄文をお読み頂き、ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • acoronel
  • ベストアンサー率50% (1/2)
回答No.3

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のアドレスを代入して初期化している』 と読めば、「気持ち悪さ」が取れると思います。

nbsp0606
質問者

お礼

>『int型のアドレスが入る変数(ポインタ)ptの宣言 をしつつ、 ついでに、変数nnのアドレスを代入して初期化している』 おそらく、そうした理解が必要なんだろうとは思っていましたが、 参考書を読むだけでは確信が持てなかったため、質問をさせて頂きました。 おかげさまで、考え方が分かり、「気持ち悪さ」を払拭することが出来ました。 ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • notnot
  • ベストアンサー率47% (4855/10270)
回答No.2

センスとしては正しいと思います。 int *pt = &nn; のイコールは代入ではないので、左辺と右辺は代入のような関係ではないです。 int *pt は整数へのポインタ変数ptの宣言で、その変数の初期値が&nnということで、意味はお書きの通り、int *pt; pt=&nn; です。

nbsp0606
質問者

お礼

>センスとしては正しい この言葉にとても救われました。 ありがとうございます。 これで混乱は解けました!

全文を見る
すると、全ての回答が全文表示されます。
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

宣言の時は、int *pt は 「int * 型の変数 pt」 だと思ってください。 つまり、*はptにではなく、intの方に付くものだと。 文法上では、カンマで区切って複数書くときは int *p, *q ; と各変数の前に*が必要ですが、ここでは、*は「ポインタから実体を参照するための演算子」ではなく「ポインタであることを表す記号」だと考えましょう。あくまで、宣言しているのは「変数p」と「変数q」です。 「初期化」と「代入」は厳密には違います。

nbsp0606
質問者

お礼

なるほど、そのように考えれば良いのですね。 何か大幅な理解ミスがあるのかと、不安に思っていましたが、 そうではないことが分かり、安心しました。 ただ単に、言語仕様がやや分かりにくい、ということだったのですね。 参考になりました。ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 参照型変数へのポインタに関してです。

    参照型変数へのポインタに関してです。 たとえば int _v[10]; int &v = &_v[0]; int *pv; pv = &v;  // 参照型変数のアドレスをポインタに代入 こうすると、pv[n]と、_v[n]は同値になります。(VC++とG++では確認) これ(この使い方)で同値なのは ・c++の言語仕様 ・コンパイラの実装依存 のどちらでしょうか? WEBを漁ると「参照型変数はエイリアス(別名)」とかかれているページがヒットするので、C++の言語仕様かなと思っています。 #もちろん配列に置き換えずに単純な参照型変数として使った場合の、値の同一性は言語仕様でしょうが。

  • ポインタに関するトラブル

    pointという座標を表す変数x,y,zつ保持するクラス型があったとして point *a = point型のポインタを返す関数(); という式を作ったんですが、なぜか、 右辺と左辺はどちらのポインタも指すアドレスは確実に同じなのに。 値を参照しようとすると違う結果が出ます。具体的には 右辺から参照した結果が 50(正しい結果) (*a).x を表示した結果 左辺から参照した結果が -9.25596e+061(?) (*point型のポインタを返す関数()).x を表示した結果 という結果で、完全に同じアドレスを保持するポインタなのに 実行した結果が違って混乱しています。まったく原因がわかりません 説明不足で申し訳ありませんが、なにが問題か分かる方がいらっしゃったらお願いしますm(_ _)m

  • C++ ポインタ 認識はこれでただしいですか?

    int i=3;// iが格納されてるアドレスは001とする そこに3の値 int *pi;// piが格納されているアドレスは//002とする pi=&i;// アドレス002にある値に001が入る printf("%p",pi);//001が表示 printf("%d",*pi);//アドレス001を参照して3を表示 printf("%p",&pi);//002が表示 Q1 このイメージであってますか? Q2 *pi= の右辺は&i,iなどいれられない   代入するときは宣言以外のときは   pi=&i のようにpi= という形にして右辺はアドレスをいれ なければならない。  これであってますか? Q3 char *pc; pc="ABCDE";//ABCDEは文字定数領域に記憶される //文字Aがアドレス(仮)005、Bが006にはいっていたとしたら ↑の式はpc=005;という意味でアドレスを代入している これでいいでしょうか?

  • ポインタにによる値の表現と文字列の表現について

    ◎1------------------------------ #include<stdio.h> int main(void) { char *pt="ABC"; printf("pt=%s\n",pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("pp=%s\n",pp); return 0; } -------------------------------------- ◎2---------------------------------- #include<stdio.h> int main(void) { char *pt="ABC"; printf("*pt=%s\n",*pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("*pp=%s\n",*pp); return 0; } ----------------------------------- ◎3--------------------------------------- #include<stdio.h> int main(void) { int ary[5]={111,222,333,444,-1}; int* pt=ary; while(1){ printf("%d ",*pt); ++pt; if(*pt==-1){ break; } } puts(""); return 0; } ----------------------------------------------- 以上3つのプログラムで、◎1はprintfで「*」が付いてなく、正常に実行出来ました。 ◎2はprintfで「*」が付いてなく、エラーは出ませんが、文字列が表示されませんでした。 ◎3は文字列ではなく値ですが、printfで「*」が付いていて正常に実行できます。 これは、値の場合は「*pt」とすることで、ptのアドレスに値を代入しているという事で、「printf("%d ",*pt);」で実行できたということですかね? 文字列の場合は、先頭のアドレスを渡すだけなので、「printf("pt=%s\n",pt);」のようにしてアドレスを参照しないとダメであるということですか? ◎2で「printf("*pt=%s\n",*pt);」としてしまうと、何が起きてしまうのかわかりません。 以上、教えていただけると嬉しいです。

  • C言語/構造体の宣言と初期設定について

    C言語初心者です。 私が使用している参考書の記載に誤りがあるのか確認したくて質問させて頂きました。 宜しくお願い致します。 struct person{  char name[40];  int height;  int weight; } struct person dt = {"山田太郎", 70, 180}; printf("%s %d %d\n", dt.name, dt.weight, dt.height); このコードで出力されるのは、 山田太郎 70 180 とのことですが、 宣言時のメンバの順番と、 初期化時の値の順番が、 上の記述だと一致していないように私には思えます。 参考書にある上記の記載は、はたして、正しいのでしょうか?

  • ポインタに ~0を入れること

    見かけたCのプログラムで、 ポインタに~0を代入するものを見ました。 そのプログラムをそのまま載せるのはわかりにくいので、 代わりに以下のプログラムを作って実行しました。 #include <stdio.h> int main(void) { char *pa[3]; int i; pa[0]=0; pa[1]=~0; pa[2]="Hello"; printf("sizeof(char*)=%d\n", sizeof(char*)); for(i=0; i<=2; i++) { if(pa[i]==NULL) printf("pa[%d] はNULLです。\n", i); if(pa[i]==(char*)0xFFFFFFFF) printf("pa[%d]は全ビット1です。\n", i); if(pa[i]==~0) printf("pa[%d]は~0です。\n", i); } return 0; } 結果 sizeof(char*)=4 pa[0] はNULLです。 pa[1]は全ビット1です。 pa[1]は~0です。 このプログラムはコンパイル時にエラーも警告も出ず、 動作も意図したとおりです。 pa[1]に入っている ~0 は、int型の定数なのでしょうか。 それならば、 pa[1]=~0; という代入や if(pa[i]==~0) という比較は 左辺はchar*型で右辺はconst int型であって型が異なりますが、 問題ないのでしょうか。 ~0は0の否定なので、全ビットは1なのでしょうけど、 int型(の定数)だと思います。 ~0というのは何か特別な値なのでしょうか。 ポインタに~0を入れるというのは、意味があるのでしょうか。 (例えば、「ポインタに0を入れるということは、ヌルポインタであって、ポインタとして無効なんですよ」のようなこと。)

  • メモリの初期値

    C言語の勉強をしている者です。 やっとこさポインタのところまでやってきまして、いろいろ試しているところなのですが、不可解な事が起こったので質問させてください。 int型の配列を作って、初期化しないままその配列[0]に入っている値を覗くと -858993460 という値が入っていました。 もう一度配列を作り、メモリのアドレスを確認すると、前に作った配列とポインタのアドレスが同じだったので そこに0を入れました。 当たり前ですが配列[0]の値は0でした。 さらにもう一度配列を作り、[0]のアドレスの中身を覗くと -858993460 という値に戻っていました ※配列[0]のアドレスは常に一緒です。 なぜこんな訳のわからない数字( -858993460 )に初期化されているんでしょうか 一度0に初期化したのなら次は0のままになっていると予測していたのですが、どうなっているんでしょうか どなたか理由のわかる方いませんか

  • 関数ポインタの利点

    こんにちは。 C言語初心者ですが今勉強中です。 その中でポインタについては理解できたのですが、 関数ポインタの利点、使うべき所などが理解できません。 ポインタの基本は理解しています。 値渡し、アドレス渡しも理解しています。 関数ポインタを使うと何がいい、またはどんなとき使わなければならないのか 教本を読んでいてもさっぱりわかりません。 サンプルプログラムを打っても何のために使ってるのかわからないです。 どなたか教えていただけませんでしょうか? よろしくお願いします。

  • 【なぜポインタを使うのか】

    私は、ポインタのメリット・デメリットを以下のように考えています。 ◆メリット メモリを多く確保しなければならないオブジェクトについて、コピー処理を行うことなく省メモリでインタフェースできる。 ◆デメリット ・関数内でしか使用しない非ポインタのローカル変数に比べ、  アクセス可能な場所が多くなってしまい、色んな箇所から値が変更されうる。(影響範囲の限定がしずらい) ・可読性が低くなる。(若いエンジニアはCの経験者は少なくっていくと思われるため、保守コストが若干割高になる) そのため、よっぽどメモリを多く使うようなオブジェクトでなければ、 (もしくは速度を重視する必要があるプログラムでなければ) 値渡しにしても良いのではと考えています。 しかし、度々目にするソースは、何でもかんでもポインタで処理しているものも多々見受けられます。 特に、int型のようなメモリを大量に使用しないものでも、ポインタで変数宣言しているケースもよく見ます。 なぜなのでしょうか? (熟練のC言語プログラマが、昔ながらの記述を踏襲しているというのはあるのかなと考えていますが)

  • 極限の教科書の基本問題で

    【lim{(a√x + b)/(x-1)}= 2 の等式が成り立つように、定数a,bの値を求めよ。】 (limはx→1です。) この問題の解き方は、 「右辺が2と有限確定の値になっているから、左辺も有限確定にならないとおかしい」 ↓ 「左辺は、x→1の時、分母→0になる」 ↓ 「だから左辺が有限確定になるためには分子も0にならないといけない」 ↓ lim(a√x + b)=0、すなわち、a+b = 0 という流れで解きますよね。 この理屈は理解できるんですが、一方で、 「左辺が0/0になっちゃったら、左辺=0で右辺=2であることとつじつまが合わなくなっちゃうのでは?」 という疑問があるのですが、どう考えたらいいですか? 実は学校の授業の時この問題を見たときも全く同じ疑問を持ち、その時は5分くらいウンウン唸ってたら「ああ、なんだそういうことか」と解決できたんです。 でもその時そのことをメモとして残しておかなかったのが悪くて、忘れてしまいました。 でも今回はどうしてもわからない(思い出せない)ので恥ずかしながら質問させてもらいました。 「勘違いしてた」系の疑問だったことは思えているのですが・・・。 よろしくお願いします。