blog.kur.jp

バイオリンと山、自転車をこよなく愛するkurのチラシの裏。たまには技術的なことを書いたりするかも知れません。

C言語入門者がポインタで躓く3つの理由

先日,とある一部上場企業で,「技術系新入社員の方にC言語を教える」と言う,とても楽しいイベントがありました.

この講義では,Windows環境にCygwinのインストールから始まって,関数やポインタや構造体等を学び,10日かけてC言語を一通り使えるようになってもらおうと言うものです.さすがに業務として受講しているからか受講生は真剣そのもの.教えるほうにも,ついつい熱が入ります.

ところで,この講義では,座学の時間よりも演習の時間をたっぷり取って,受講生に,自分の手を動かしてプログラムを組んでもらっています.具体的には,講義時 間の3分の2以上を演習と,その解説に当てています.演習時間中は,教室の中を歩き回って,どんなプログラムを書いているのかを覗き込んだり,質問 に答えたりしています.

やっぱり,プログラミングができるようになるためには,実際に手を動かしてもらうのが一番じゃないかなと,私は思うのです.もちろん,自分で本を読んだ り,講義で説明を聞けば,動作原理を学ぶ事は出来るのだけれども,それだけではプログラムを読めるようになっても,書けるようにはならないんじゃないかと.

で,講義も回数を重ね,ついにC言語講義で最大の難関と思われるポインタへ.

ポインタってのは理解してしまえばそんなに難しいことでは無いと思うんだけど,ここでプログラミングが苦手になってしまう人ってのは,それなりに居るらし いです.実際,C言語のポインタだけを扱った書籍もそれなりにあったりします.

こんなのとか,

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

こんなのとか.

図解C言語 ポインタの極意

こういう状況になってるのは「なんでかなー」ってのは以前から思っていたんですが,今回,C言語を教えると言う機会を頂いたことによって,なんとなくその理由がわかってきました.

たぶん,ポインタが理解できないって言う人には,3つのパターンがあるんじゃないかと思うのです.

  1. ポインタの仕組みが理解できない.
  2. ポインタをどう使えば良いのかわからない.
  3. コードにする方法が良くわからない.

以下,順番に考えてみます.

ポインタの仕組みが理解できない.

1については,コンピュータが動作する仕組み,というかCPUとメモリの関係が理解できていないのが,原因なのかなーと思っていたりします.プログラムって言うのは小さな命令の集まりなんだけど,コンピュータでプログラムを実行するときには,これらの小さな命令を順番に実行していくわけです.で,これらの小さな命令が,どこにあるかって言うと,メモリっていうところに保存されてて,それぞれに番地が振ってあるわけです.

で,プログラムで計算した結果ってのは,どこかに保存しなきゃいけないわけなんですが,この保存先も,やっぱりメモリなんですね.つまり,同じメモリなんだけど,ある番地には,小さな命令が入ってて,ある番地にはデータが入ってる.わかってる人には,「あー,そうだよね」で済みそうなところなんだけど,プログラミング初心者には,まずここで????ってなってしまうのかもしれません.

このパターンの人には,ポインタの説明をする前に,コンピュータの動作原理をしっかりと理解させること.図などを使って,頭の中でイメージできるようになってもらうと良いかもしれません.

ポインタをどう使えば良いのかわからない.

2のパターンについては,コンピュータの動作原理は何となくわかったけど,実際にどうやってポインタを使えば良いのかわからないっていうパターン.必要性がわからないから,理解使用ともしない.事実,ポインタなんか無くたって,動くプログラムを書くことは可能です.そんなことは,JavaやらPHPやら,他の言語の仕様を見れば明らかなわけで.

このパターンの人には,ポインタを使うことで,何が嬉しいのかということを説明すること.こういうのって数学とかでも同じだと思うんだけど,フーリエとか,マクローリンとか,やり方だけ教えてもらっても,人間って使い道が見出せないと,すぐに忘れちゃうもんだと思うんです.なので,ポインタを使うメリットを,演習問題を通して手で,頭で理解してもらうことが大事なのかなーと.

コードにする方法が良くわからない.

そして,最後の理由.コンピュータの動作原理はわかる.ポインタの有用性もわかる.だけど,コードへの落とし込み方がイマイチわからないって言うパターン.ユーザビリティに興味のある人だとかで,DAノーマン先生の著書である「誰のためのデザイン」あたりに目を通している人なら,わかるんじゃないかか思うんですが,1つの記号に,複数の意味を持たしちゃってるのが,学習者に混乱をもたらしているんじゃないかと.

ようするに,変数宣言時と,処理時で,*の意味が異なることで,混乱しちゃってるパターンが,結構見受けられたんです.どういうことかっていうと,変数宣言時にはポインタは,

int *a;

みたいにして宣言することが出来る.これはint型の変数のアドレスを入れるための箱を用意しなさいって言う意味.ところが,実際にプログラムの処理部でポインタを使うためには,

*a = 1000;

みたいにして記述すると,「ポインタaが指すアドレスに,1000を代入しなさい」と言う意味になっちゃう.宣言したときは,aはアドレスを入れるための箱だったんだから,処理するときも,このように記述したら,aに1000と言うアドレスを入れたい,とかそう思っちゃうのかしら.ようするに,かっこよく言えば,メタファーだとか,コンテクストとか,そういう言葉で表現できるんだろうけど,これは初心者を混乱させるための罠であることがわかった.

事実,記号は,コンテクストによって,意味が違うので注意してくださいと言うことを受講生に説明したところ,あまり混乱は無かったようにも思うのです.たったこれだけなんだけど,「は書く場所によって意味が違う」って言うことを,知っているか知らないかで,学習効率は大分違うのかなーとか思ったり.

こんなこと,人に教える機会でもなければ,絶対に気がつかなかったし,特に今回は30名ほどが受講していて,各人が詰まる箇所がマチマチだったので,ポインタのどこが理解しにくいのか,についても,考えることが出来ました.それにしても,人に何かを教えるって言うのは,自分のためにもなるんだなーって再認識.