From seiji@sunday.rsl.crl.fujixerox.co.jp Mon Jun 14 08:20:08 1999 Path: fucc!east-news.csi.ad.jp!news.csi.ad.jp!aist-nara!itakura-news!tamaru-news!Q.T.Honey!nf.asahi-net.or.jp!news1.kddnet.ad.jp!newssvt07.tk!nntp-egw.ocn.ad.jp!nd-tk001.ocn.ad.jp!newsgw.exp.fujixerox.co.jp!atlas.rsl.crl!seiji From: seiji@sunday.rsl.crl.fujixerox.co.jp (Seiji Suzuki) Newsgroups: fj.comp.lang.c Subject: Re: 誰かポインタについて教えてください。 Date: 10 Jun 1999 04:51:05 GMT Organization: Fuji Xerox Co., Ltd., Kanagawa, Japan Lines: 111 Message-ID: <7jng7p$2ll$1@atlas.fen.crl.fujixerox.co.jp> References: <7jj840$n5a$1@news-jp1.nifty.ne.jp> NNTP-Posting-Host: sunday.rsl.crl.fujixerox.co.jp X-Newsreader: mnews [version 1.21] 1997-12/23(Tue) Xref: fucc fj.comp.lang.c:4046 In article <7jj840$n5a$1@news-jp1.nifty.ne.jp> QWF00124@nifty.ne.jp writes: >> 最近c言語を勉強してますが、どうもポインタのところでひっかっかってしまいま >> す。なにか良い理解の方法はありますでしょうか 私にもそーゆー時代があったなぁと思いながら思わずフォローしました。 実際には慣れの問題もありますから、どんなに分かりやすい説明を読んで わかっても実際にプログラムが書けるかどうかは別問題です。小さなテスト プログラムをたくさん書いて、いろいろいじくりまわしてどう動くか、 なぜそう動くのか考えてみるのが一番でしょう。 注意) 以下の説明は「雰囲気」を私なりに説明したもので、厳密ではありません。 この説明でC言語のポインターが確実に解説できているわけではありません。 整数の間の演算を説明する際に「バナナが2つとりんごが3つありました。 あわせていくつでしょう」といって解説している程度のものだと思って 読んでください。 ※値渡しとポインタ渡し ポインターと言うと結構難しいと考えがちですが、ポインターや値渡しは 日常でも良く使われる概念です。分かりやすい例かどうかは分かりませんが、 例えば明日の天気を誰かに聞かれたとしましょう。そこで、「神奈川県の 明日の天気は晴れ時々曇山沿いではにわか雨、海上の波は...」と新聞の 天気予報を読み上げるか書き移して渡すのが値渡し。「そこの新聞みれば」と そっけなく答えるのがポインタ渡しです。C 風に書くと、 ○値渡し void 天気を知りたがっている誰か( char, ... ); 天気を知りたがっている誰か( '神','奈','川','県','の', ... ); (※)型が違うというのはまあいいとして。 ○ポインタ渡し void 天気を知りたがっている誰か( char * ); char *新聞 = "神奈川県の..."; 天気を知りたがっている誰か( 新聞 ); /* なんか C 言語会話みたいでやだなぁ。*/ 「〜渡し」というと関数間の引数みたいな印象を受けますが、変数どうしの やりとりでも一緒です。この二通りのやりかたは、それぞれ一長一短あり、 それも、場合によりけりです。例えば、どこか他の関数(たとえば printf )に 文字列を渡す場合、文字列そのもののコピーを渡すと文字列の長さによっては 非常に時間がかかる場合があり、効率的ではありません。したがって文字列は 長さにかかかわらずポインタ渡しにするのが普通です。データーとして短い 例えば整数なんかは値渡しにするのが普通です。ただ、ポインター渡しを した場合、相手先がその実体に直接手を触れる事が出来ます。したがって、 相手に書き換えを要求する場合などには短いデーターでもポインター渡しに します。試験でいうと、面接試験は値渡しです。筆記試験はポインター渡しです。 答案用紙というメモリーに書くよう指示され(ポインターを渡され)、その 答案用紙にアクセスして試験管が採点します。(答案用紙が物理的に移動します から、実体をやり取りしている値渡しのようにおもえますが、この移動は 本質的ではありません。答案用紙が机に貼り付けてあっても回答や採点は 可能ですから。場合によっては黒板に書いて答案とする場合もありますし。) ※ポインタへのポインタ ここまでのことはすぐに分かると思いますが、私はポインターへの ポインターが絡むと自分が何をさしているんだか分からなくなってしまう 事がよくありました。このへんは慣れですね。 ちなみに、ポインターへのポインターと言うには宝探しゲーム(知ってます?)に 似ています。メモがあって、そのメモを見ると次のメモの場所が書いてあって、 次のメモにはそのまた次のメモの場所が...と言うやつです。これを C 風に 書くと、 char *********宝; 宝 = 最初のメモ; /* がある所 */ *宝 = 次のメモ; /* 以下、次のメモの隠し場所を */ **宝 = ロッカーの2番目;/* 次々にさしていく。当時は */ ***宝 = ポチの糞の下; /* この初期化が一番面白かった。 */ 中略 ********宝 = "楽して300万儲ける方法..."; ※ポインタの初期化 実際の世界は3次元ですし、いろいろな構造物がありますから「どこどこの下」と いう言い方をしますが、コンピューターのメモリーは1次元ですし、特にこれと いった構造もないので、ポインターの中にはメモリー上での場所を特定できる 無味乾燥な数値が入っているだけです。その数値はプログラムを組む際に与えて やらなければなりません。私はこれにぴんとくるのに時間がかかりました。 char *ptr; と宣言しただけではほとんど無意味です。つまり。「人差し指がある」という 状態でしかありません。よく人に「そこに置いといて」といって指差すことが ありますが、それは指差す先がちゃんと意図した場所を指しているという前提が 必要です。ありもしない場所を指差してもあいてはこちらの意図したとおりに 物を置いてくれるかどうかわかりません。もしかしたらこれが原因で物が なくなるかもしれません。コンピューターでも同じでポインターを使って操作 する前にちゃんとした場所を指し示すようにしなければなりません。この辺は 場合によっていろいろなパターンがありますから詳しくはその辺の解説書を 参照してください。そして、プログラムを組む際は常に今扱っているポインターが 何を指しているのかを意識して書くようにしてください。でないと、CPU は とんでもないところをいじってしまってプログラムは動作不良を起こして しまいます。 ※インデックス 同じような構造が並んでいた場合、代表点を一つ示し、ほかはその代表点からの 相対位置で示したほうが便利なことがあります。たとえば、ロッカーの場合、 私はロッカーの7番、竹内さんは3番、山川さんは8番というように、ロッカーの 1番を基準にn番目という言い方をすると「だれだれさんは何番」というように 簡単な言い方にまとめることができます。ポインターでも同様に、 *(locker+2) = *(locker+5); /* 5番のlockerの中身と同じ物を2番に入れる */ というように、ポインターに対して相対位置を指定することができます。これを 利用すると、コンピューターお得意のループでまわして大量のデーターを一気に 処理するといったプログラムが簡単に書けるようになります。 from Seiji.Suzuki@fujixerox.co.jp From minesita@rd.njk.co.jp Thu Jan 27 17:34:55 2000 From: minesita@rd.njk.co.jp (Hiroyuki Minesita) Newsgroups: fj.comp.lang.c++ Subject: Re: [=?ISO-2022-JP?B?GyRCPEFMZBsoQg==?=] =?ISO-2022-JP?B?GyRCJV0lJCVzJT89aUpiGyhC?= Date: 19 Jan 2000 06:53:24 GMT Organization: NJK CORPORATION. Japan Lines: 37 Distribution: fj Message-ID: <863n15$3m8$1@sunny.njk.co.jp> References: <863m98$h1g$1@nh1.u-aizu.ac.jp> NNTP-Posting-Host: nala.njk.co.jp Mime-Version: 1.0 (generated by MimeKit/1.8) Content-Type: text/plain; charset=ISO-2022-JP In-Reply-To: s1061097@u-aizu.ac.jp's message of 19 Jan 2000 06:40:40 GMT X-Newsreader: gnspool [Version 1.40 Jun.1,1998 (DOS32)] X-Forwarded: by - (DeleGate/5.9.12) Path: hannan-nwsv1!hannan-hu-entry!odins-toyonaka!news.cs.ritsumei.ac.jp!itakura-news!onodera-news!newsfeed.gamma.ru!Gamma.RU!newspeer1.nac.net!newsfeed.yosemite.net!newsfeed.wizvax.net!news.interq.or.jp!spin-hsd1-tky!spinnewsgate!spin-hsd0-tky!abu!sunny!minesita Xref: hannan-nwsv1 fj.comp.lang.c++:4623 >From article <863m98$h1g$1@nh1.u-aizu.ac.jp> by s1061097@u-aizu.ac.jp #変な譬えにしてしまいます。(^^; > 初心者です。質問なのですが、 > #include > #include > > main(){ > char *p,*p2; > > while(cin >>p2){ > printf("%s",p2); > }} > > このように宣言して、最初にp2を使うとうまくいかないのはなぜでしょうか。  家には人が住めるけれど、アドレス帳には人が住めないのと 同じ様な事です。 > キーボードから、文字列を2つ読み込でそのまま出力する自作関数はどうしたらいいのですか。  家を造りましょう。  ここで言う譬えは……   家     …… 文字列を格納する実体のメモリ領域   アドレス帳 …… ポインタ   人     …… 文字列 と言うことになります。 --- @) ---------------------- 〃 (・>            ヾ<・) ι ν 峯下博幸        ( ~彡 (m_m)っ ---------------------- κκ