新・闘わないプログラマ No.101

C言語講義


えー、それでは今日は皆さんお待ちかねの「ポインタ」のところに入って行きたいと思います。あ、そこ、今いやな顔しただろ。おまえだよ、おまえ、渡辺、なんだよ、その顔は。
「いやあ、だって……」
だって、なんだよ。
「だって、先輩にも聞いたんですけど、『C言語のポインタは難しいぞー』って」
あれ? なんかみんなもうすでに脅されているの? 簡単だよ、ポインタなんて。それが証拠に私ごときだって講義できるくらいなんだから。あ、そこ、いま笑ったな。ほら、あなただよあなた、伊藤さん、なんか言いたいことあるの?
「……」
んー、どしたのかなあ、おぢさんにぜーんぶお話してごらん??
「ほんっっとーに簡単なんですかあ?」
あ、おまえ私のこと信用して無いだろ?
「信用してないことはないんですけどお、でもお……」
でもおおおお、なんだよ。
「いえ、いいです」

じゃあ、無駄話はこれくらいにして、早速「ポインタ」のところに入っていきたいと思います。テキスト(注:「プログラミング言語C 第2版」B.W.カーニハン/D.M.リッチー著 石田晴久訳 共立出版)の113ページ「第5章 ポインタと配列」のところを見てください。最初のところにこんなことを書いていますよね。

ポインタは、他の変数のアドレスを内容とする変数であり、Cでは頻繁に使用される。

ここの「ポインタは〜変数であり」というのは、原著でも同じこと書いてありますけど、ちょっと問題のある表現だと思います。「ポインタ」という言葉を使った場合、変数のことを言っているわけじゃない場合もありますから。それはまた後でお話します。
それはともかく要するに、ポインタと言うのは、C言語でアドレスを取り扱うための仕組みだと思ってもらえばいいと思います。皆さんはもうすでに、第二種情報処理技術者試験の勉強で、CASLというアセンブリ言語をやったかと思うのですが……あれ? なんかいま、下を向いた人間がちらほらと……やりましたよね、ね、ね、中村君。
「あ、はい、やりました」
ちゃんと覚えていますよね、いま下を向いた川本さん。
「……」
なんだよ、思いっきり首を左右に振っているそのしぐさは。
「一応やったんですけどお、でもお……」
でもお、なあに?
「わっすれちゃいましたあ」
あのなあ……まあいいや。とにかくですね、アセンブリ言語では直接アドレスを扱って処理を行うわけですけど、C言語の場合はどうか、と言うと、昨日までの内容ではアドレスを扱うというようなプログラムは無かったわけです。じゃあ、C言語ではアドレスを扱えないか、というとそうではなくて、このポインタというのを使えば、アドレス、ただしアセンブリ言語と違って抽象化してありますけど、とにかくアドレスを取り扱うことが出来るわけで、その仕組みがポインタなわけですね。
さて、テキストをもう一度見てください。

その一つの理由は、それが時として計算を表現する唯一の方法であるためであり、もう一つの理由はこれで他の方法で得られるより通常はもっとコンパクトで効率的なプログラムが書けるからである。

なんか分かりづらい表現ですねえ、どうも訳がよくないんですよねえ、この訳本。やっぱり英語の原著を使えばよかったかなあ。あれ? また首を振っている人間が見受けられるけど、どしたの? そこの石井君。
「日本語でいいです」
じゃあ、同じく首を振った中野さん。
「私も日本語でよかったと思いまーす」
あれー、皆さん英語できるんでしょ? 確か入社試験のときにTOEICだかなんだ、そんなのがあったはずだよね。私のころはそんなん無かったんだから。私なんかより、もっと、ずーっと、はるかに、とてつもなく、英語が出来るはずだよねー。ほら、なんだよ、そこで、顔の前で思いっきり手を振っている君、えーと名前なんだっけ? あ、そうそう中崎さん。
「えーご、できませーん」
あのなあ。でもね、ここだけの話だけど、この手の英語って文学的表現とか、そんなんが無いから簡単だよ。それに、仕事では英語のマニュアルとか資料とか読む機会が多いし。
まあ、余談はそのくらいにして、テキストに戻りますけど、とにかくC言語ではポインタを使わないと表現できない処理があったり、ポインタを使うと非常にコンパクトにプログラムを書けたりする、ってことが書いてあるわけです。
まあ、これは後でまたお話しますけど、C言語で配列を扱うときには必ずポインタを使うことになります。配列についてはもうすでに、「第1章 やさしい入門」で出てきていて、そこでは別にポインタなんか出てきていなかったじゃないか、と思われた方もいるかも知れませんけど、実はあそこでもこっそりポインタが使われています。

さて、じゃあ実際にC言語でポインタを扱うにはどうしたらいいか、というところに入っていきます。テキストの114ページを見てください。

    int *ip;

これが、ポインタ変数の定義、まあ宣言の場合もありますけど、の書き方です。ここで注意が必要なのが、変数名は「ip」だということです。一見すると「*ip」が変数名のように思えますけど、違います。変数名はあくまで「ip」です。で、その変数「ip」の型が「int *」です。いいですか? 一木君?
「はい、大丈夫です」
ですから、この定義で、「ip」という変数が定義されて、それ用の領域……まあ、いままでも箱なんて言っていましたけど……が確保されるわけです。で、この箱に入る値の型が「int *」型だ、ということなんですけど、これが「ポインタ型」と呼ばれるものです。簡単に言えば、このipという箱は、アドレスが入る箱だと思ってください。
さて、そこで、

    int x;

というint型の変数xがあったときに、

    ip = &x;

とやると、ipというポインタ型の変数には、xという変数のアドレスが入ります。いいですか? わかりますか? アセンブリ言語でも似たようなことができますよね? ここで「&」という記号は単項演算子で被演算数のアドレスを求める演算子です。ここで、

    int y;

というやっぱりint型の変数yがあったときに、

    y = *ip;

とやると、ipというポインタ変数の差している先、つまり、ipという箱に入っているアドレスにある値がyに代入されます。この「*」は掛け算の演算子ではなく、間接参照の演算子になります。

さて、そろそろ時間になりましたので今回はこのくらいにしますが、どうですか? 簡単でしょ? ポインタの考え方はたったこれだけです。ね? 簡単ですよね、小山さん?
「あ、はい。ここまでは……」
ここまでは、というか、ポインタの基本的な話はこれだけなんですよね。別にむずかしいことなんて無いでしょ? まったく、誰だよ、「ポインタは難しいぞー」なんてデマを流してるやつは。
「でもお」
ん? なに? 鈴木君。
「でも、テキストのこの章、あと40ページもあるんですけど……これから難しくなるのではないんでしょうか」
ううむ、いいところに気づいたねえ、鈴木君。まあ、それは次回以降のお楽しみ、ということで。
「あ゛ー、ごまかした。やっぱり難しいんだあ」
うるせ、佐々木。
じゃ、今日はこれでおしまい。続きはまた次回。

[前へ] [次へ]

[Home] [戻る]


mailto:lepton@amy.hi-ho.ne.jp