大学での初心者に対するプログラミング講義ではC言語を使うべきでない

  • 6
    いいね
  • 2
    コメント

今日、大学に入って最初のプログラミングの授業があった。それについて少しばかり思うことがあったのでここに記す。以下の文章は、工学部情報系学科一回生の、最初のプログラミング授業について述べたものである。タイトルにもある通り、この文章は「初心者に対する」講義について言ったものであり、機械制御を専攻する学生に対する講義などを言うわけではない。

最初の言語がC

結論から述べよう。最初のプログラミング言語にC言語は向いていない。できないとは言わないが(私が最初に触れた言語もCだが)、より有力な候補がいくらでもある。私の所属する学科には機械分野に進む人も多いので、それに使われるCを、という思惑もあるのだろう。しかし、初心者が「プログラミングを」学ぶ言語としてはお世辞にも良いとは言えない。私が思うプログラミング初心者に向いた言語とは、次の条件を満たすものである。

  • 現在普及している
  • 環境構築が容易(私の大学では大学が用意したコンピュータを使うのでこの項目は関係ない)
  • 動的型付言語
  • 十分高レベルに抽象化されている

一番上に関しては異論を唱える人はいないだろう。二つ目についてだが、以前どこかで環境構築を自分で調べながらできるだけの能力がなければプログラミングをするのは難しい、といった主張を見かけた覚えがある。これは私も賛成だが、少なくともプログラミング自体が完全に初めてという人に強いるスキルではないはずだ。初心者がまず覚えるべきなのは、プログラミング言語とは、変数・関数とは、といった内容であり、適切に検索する能力ではないと思う(もちろんゆくゆく必要になるのは疑いようがない)。

三番目では少し反論のある人がいるかもしれない。私自身は静的型付言語の方が動的型付言語よりも優れていると考えているが、プログラミング初心者に教えるという目的には向いていないと思う。他にも同様の観点として、コメント、テスト、抽象化、モジュール化などがあげられるだろう。いずれもプログラマーにとっては品質を高めるために重要なことだが、初心者が気にするべきことではない。例えば、コメントというのは他人や後の自分がソースコードの意図を理解できるようにするものである。しかしプログラミング初心者が書くソースというのは概してHello, World!や簡単な計算にとどまる。また、一度書いたプログラムを見直すということもない。プログラマーがコメントを重要だと考えるのは、(自分のものであれ他人のものであれ)コメントがないソースコードを読んでさっぱり理解できなかった経験に基づいている。その経験がない初心者に対してコメントの書き方を教えるのは、情報の過剰供給であり、たいていの場合教えた情報の中からどれかが抜け落ちていく。

最後に、四番目の抽象化について説明する。C言語は「機械語やアセンブリ言語に比べれば」なるほど抽象化された言語ではあるが、プログラミング初心者が扱うには間違いなく低レベルすぎる。特に文字列の扱いを見ればCとその他のモダンな言語とでは雲泥の差がある。メモリだのアドレスだのといった知識はプログラミング初心者に必要なものではないし、コンピュータの動作原理に関して造詣の深いプログラミング初心者はなかなかいない(それを知っているならまず間違いなくプログラミングにも手を出しているだろう)。C言語はプログラミングをする上での基本知識が詰まった言語ではあるが、プログラミング初心者に向いているとは言い難いだろう。

では、上の四つの条件を満たす言語とは何か。これは人によって様々な意見があるだろうが、おおよそ以下のような言語ではないだろうか。

  • Python
  • Ruby
  • JavaScript

なお、初心者向けの言語はオンラインでインタラクティブに実行できることが望ましい(上の三つはいずれも満たす)。なぜなら、大半の学生はCLIに慣れていないからである。なんども述べたことだが、CLIの操作はいずれ必要になるスキルかもしれないがプログラミング初心者には必要ない。

まとめ

上の文章で再三述べたことの繰り返しだが、プログラミング初心者を教えるときには、「いずれ必要になること(知識・スキル)ではなく、今必要なことだけを伝える」ことが重要である。初心者に与える情報量は少なければ少ないほど良い。

蛇足

授業で使われていた資料を見ながらツッコミを入れる。これは実際のスライドの順番に従っているわけではなく、全てのスライドについて言及しているわけでもない。


プログラミング言語の例
* マシン語 ・・・ 可読性が悪い 70年代 0と1など数字のみ CPU依存
* アセンブラ言語 ・・・ 具体的な命令をアルファベットで記述
* C言語 ・・・ 可読性がだいぶまし ANSI規格であればCPU依存がない
* FORTRAN ・・・ 数学科学計算に特化 でも今は使われない
* BASIC ・・・ インタープリター言語 ・・・・・その他いろいろ

うーん.....古い。実際は「その他いろいろ」を触ることの方が圧倒的に多いので、そちらをもう少し(名前だけでも)書いておいてほしいところ。プログラミング言語の歴史と変遷、とかならまだわかる。


C言語
* 人間の言葉に近いプログラミング言語
* 処理速度 速い
* オールマイティな言語
* 将来に他のプログラミング言語を学ぶ時に役立つ

最初の項目は「機械語やアセンブリ言語に比べれば」が抜けている。最後の項目も、役立つのは確かだろうが間違いなく「今」つまづく。


#include <stdio.h> /* おまじないのようなもの */

この「おまじない」という表現はネット上でも多くの例が見つかるのだが、非常に違和感がある。「説明するのは難しいが必要なので、エラーが出ないように書くもの」というくらいの意味で使っているのだろうが、それならそういった方がはるかにわかりやすいと思う。それを一言で「おまじない」などと言おうとするから初心者に対してしか使われないにも関わらずプログラミング経験者でないとわからない、という皮肉な現象が起こる。なお、私がRubyやPythonを勧めるのはこうした「おまじない」がほとんど存在しないというのも理由にある。

ところでこの講義にはプリプロセッサの説明も含まれていた。こうなると#includeは意味を持った行なのだから、もはや「おまじない」ですらない。


主なデータ型

意味 ビット数 表現できる範囲
char 文字 8 0~255及び1つの半角文字
int 整数 32 -2147483648~2147483647
short 整数 16 -32768~32767
long 整数 32 or 64
unsigned int 整数 32 0~4294967295
unsigned short 整数 16 0~65535
unsigned long 整数 32 or 64
float 実数 32 有効桁数最大約7桁 ±3.4×1038 ~ ±1.4×10-45
double 実数(倍精度) 64 有効桁数最大約15桁 ±1.7×10308 ~ ±4.9×10-324
unsigned double 実数 64 or 96

実はCPUによって変わるものもある.マイコンなどでは注意 PCでは現状32bit

まとめのところで述べた「必要なことだけを伝える」に思いっきり反している。intdoublecharがあれば当分は十分だろう。他にもこの資料はprintfの書式をやたら網羅的に書いていたりと、情報の過剰供給が目立つ。


変数名の注意
* 変数名には,A~Z,a~z,0~9とアンダースコア( _ )が利用できる.
* 変数名の先頭は,必ず,半角英文字でなければいけない.
* 最初の31文字で区別
* C言語の予約語は利用できない
+ 変数のデータ型を表す int, float, char,...
+ 組み込み関数である printf, scanf,...

最初の31文字しか有効でないコンパイラを初心者が使うことなどありえない。今回の講義で使ったコンパイラはCygwinのgccであり、もちろん32文字以上の変数・関数を扱える。

なお、printfscanfは変数名・関数名として有効であり、予約語ではない。しかし、コンパイルエラーがでる可能性が高いので(そしてそのエラーをもちろん初心者は解決できないので)、初心者に教えるという意味ではこの書き方で正解だと思う。


関数定義の一般形

返り値の型 関数名 (引数1,引数2,…)
    引数の宣言
{
    処理内容
}

古い。まさかANSIよりも前の書き方を見ることになるとは。ここまで古い書き方だと、この記事を読んでいる人の中にも知らない人が確実にいるだろう(ANSI-Cの制定は1989年である)。私もこの書き方は少し前のvimのソースコード(古いコミットを辿っていけば見られる)でしか使われているのを見たことがない。なお、この講義でもこれ以外の箇所ではANSI-Cの書き方で書かれてあった(なんで訂正してないんだ......)。


全体的に内容があまりに多すぎる。今回の授業の課題に必要ない部分まで過剰に情報を与えてしまっているため、プログラミングができる学生以外はパンク状態になっていた。

このスライドに含まれていた情報:

  • プログラミング言語とは
  • C言語とは
  • GUIプログラミング
  • コンパイル・リンク・実行
  • コメント
  • main関数
  • 関数定義
  • printf・scanf
  • プリプロセッサ
  • 配列
  • 変数
  • オーバーフロー
  • キャスト
  • 演算子
  • 代入

明らかに多すぎる。この記事を書くために今一度見返して見ると重複部分もかなりあった。そのため実際にはこの1.5倍程のボリュームに感じる。