«前の日記(2007-08-17 (金)) 最新 次の日記(2007-08-21 (火))»  

まちゅダイアリー


2007-08-18 (土)

プログラミングと初心者

神様なんて信じない僕らのために - Cの老害?を読んだ。

まず配列がわからない子はプログラマにならなくて良い。 アルゴリズムとかデータ構造が理解できない子もプログラマにならなくて良い。 どうして配列がわからない子をプログラマにしないといけないの? 運転技術がなく理解もできてない人をタクシーのドライバや旅客機のパイロットにしたい?

「興味ない」と思っている人はWebとか上層レイヤを選ぶ。 「興味ある」と思っている人は組み込みとか下層レイヤを選ぶ。 どうせ、そのレイヤ層の中にも上澄みと沈殿物があるんだから。

後半は賛成だけど、前半は見方次第かなって思う。 しばたさんが「まともなプログラム」かそうでないかなんて国際基準があるわけでもないと言っている通りかなぁ。

例えばRailsを使ったWebアプリの場合…

Webアプリケーション
ActiveRecord, ActionPack
ActiveSupport
Rubyライブラリ
Rubyコア
C言語
アセンブラ
機械語
---
CPU, メモリ
半導体
シリコン
…

と、いろんな層が重なり合って出来ている訳で、全てを知ることは無理だし。 これだけ複雑なものがこれだけたくさん使われるようになったんだから、それぞれの層で分業するしかなくて、アルゴリズムやデータ構造が分からなくても活躍できる分野はあるんじゃないかなぁ。

もちろん、「プログラマ」として比較した場合に、低レイヤを知っていることは強みになる。 でも、低レイヤのことを勉強する時間を、プログラミング以外の他のことを学ぶために費やす選択肢もあってもいいんじゃないかな。

以下、カレーなる辛口Javaな転職日記 - 初心者向けの言語より引用。

LISPのような関数型言語やRubyのようなスクリプト言語は,初心者には良くないと思う.すべからく抽象度が高すぎて,初心者だと「(ノイマン型)コンピューターの内部では,あんな風に動作してるんだ」と誤解する危険もある

これも一理あるけど、プログラムが期待通りに動けばよくて、コンピュータの内部でどう動いているかなんて興味が無い人もいる気がする。 高度なデータ操作や動作速度を追求するのでなければ、抽象度が高い状態でプログラミングできるというのもアリなんじゃないかなぁ。 配列やポインタが理解できない素質が無い人でもプログラムが書けるようになれば*1、それも一つの利点になる。 Windowsが良くも悪くもパソコンを誰でも簡単に使えるようにしたようにね。 (繰り返しになるけど、低レイヤの知識が不要って訳じゃなくて、あくまで分業の話)

Tags: memo

*1 バグや脆弱性がないプログラムが書けるという前提ね

ポインタの難しさ

僕はポインタの概念を理解するのにかなり苦労した。 一度分かってしまえば単純なんだけど、その壁を越えるのは大変。 たぶん、エクスプローラからブートセクタが見えない話と同じで、考え方の枠を広げるまでは理解できなかったんだと思う。 理解する障壁になっていたのは…

  • 一見すると他の変数と同じように見える(まぁ、値がアドレスというだけで、同じなんだけど)
  • 最初に学ぶ時点では何に使えるのかが分からない

例えば、C言語の教科書に以下のようなサンプルが出てくる。

int a;
int *x;

a = 10;
x = &a;
*x = 20;
printf("%d\n", a);

今見ると、ポインタの本質を書いてると思う。 でも、分かっていない時は、以下のプログラムとの違いが分かんなかった。

int a;

a = 10;
a = 20;
printf("%d\n", a);

なんでわざわざ「*」とか「&」を使ってaの値を変える必要があるの?と。 配列とポインタが一緒というなら、ポインタを使わずに配列を使えばいいじゃない?とも。

たぶん、ある機能や概念を説明するときには、そのものの性質だけを説明しちゃダメで、それがなぜ必要なのかを先に説明したほうがいいんだろう。 ポインタを教えるときは、ポインタを使わないと実現できない例を最初に見せるといい気がする。 僕は関数の参照渡しの説明を聞いて、ようやくポインタの役割を理解できたなぁ。 (もっといい例がありそう。思いつかないけど。双方向リストとか?)

追記

やっぱり文字列操作のプログラムかなぁ。 でも、ある程度は配列だけで頑張れちゃうんだよね…。

Tags: memo
本日のツッコミ(全10件) [ツッコミを入れる]
hidetox (2007-08-19 (日) 06:52)

ポインタが重要といえば構造体(struct)じゃないですか?<br><br>あと、関数ポインタ(例えばint(int*)みたいな)は標準ライブラリ関数signalにも使われているテクニックだけど、ポインタを理解していないと関数ポインタも理解できないかなーと。<br>RubyのProcとか、JavaScriptでのfunc()とfuncの違いを知ってる人には簡単に理解できるかもですね。

hyuki (2007-08-19 (日) 21:23)

ポインタは「オブジェクト」を実装しようとしたところで重要性に気づきますね。アイデンティティとしてのポインタ。

どぅ (2007-08-20 (月) 16:40)

どもです。長文失礼。<br>個人的に思うポインタの難しさって言うのは。。。<br>・int func(char str[10])...の「char str[10]」は「char *str」と同義で、配列ではない。え?そうなの?<br>・char*型とint*型は、32bit環境なら両方とも4byteだよね。じゃあ何が違うの?同じ型じゃないの?<br>・char *p = "string";とchar a[] = "string";は意味が違う。え?両方ともchar型の配列じゃないの?<br>・val = a[10];の[10]はポインタ演算を意味していて、aは必ずしも配列とは限らない。ポインタかもしれない。<br>・main(int argv, char *argv[])のargvがchar**型の変数であるということ。argvの指す先に何があるのか、そのさらに何があるのかは決まっているが、この宣言のみでは判断できないということ。ポインタの配列があるんじゃないの?(実際上はそうだが、宣言自体は、必ずしも配列の存在を規定していない)

どぅ (2007-08-20 (月) 16:42)

う、誤りハケーン<br>誤:main(int argv, char *argv[])<br>正:int main(int argc, char *argv[])

まちゅ (2007-08-21 (火) 05:02)

>hidetoxさん<br>構造体を学んでいるときはなおさらポインタと変数の違いに混乱していた記憶があります。なんでだろう…。<br>関数ポインタはCを勉強している時には意味不明でした。Javaでオブジェクトの概念を覚えた後はすんなり理解できた気がします。<br><br>>hyukiさん<br>ポインタがアイデンティティだとすると、普通の変数は何になるのでしょう。<br>興味深いのでちょっと考えてみます。<br><br>>どぅさん<br>配列とポインタの違いは今でも完全に理解できていない気がします。<br>char *p = "string"; と char a[] = "string"; の違いが分かりませんでした…。

まちゅ (2007-08-21 (火) 06:23)

ちょっと仮説です。<br><br>ポインタがないと実現できないことを考えてみました。<br>1. 複数の変数が一つの値を参照する。<br>2. 実行時にサイズが変わるデータを扱う(可変文字列、リスト)。<br>3. 関数ポインタ<br>これが正しければ、ポインタの説明にはこれらの例を使うのが良さそうです。<br><br>もう一つ、「ポインタとは何か?」の説明だけでなく、「変数とは何か?」の説明が必要かもしれません。<br>1. 変数の型は誰が管理しているのか(ファイルシステムとMBRの話みたい)<br>2. 配列のサイズは誰が(略)<br>3. 変数の代入はコピー。構造体の代入は?(RubyやJavaでの数値とArrayの代入の違いは?)

どぅ (2007-08-21 (火) 15:08)

どもです。Rubyは勉強始めたばかりなのでよろしくお願いします。m(__)m<br><br>ポインタの用途で最初に思いつくのは、<br> 1.関数の引数で返り値をもらう<br>です。Javaだとオブジェクトはデフォルトで参照呼び出しになってますね。<br>あと、Cだと<br> 2.配列の要素にアクセスするとき<br>です。Cでは配列へのアクセス x = array[3];はポインタ演算です。<br>つまり x = *(array + 3);っていう意味です。<br><br>先の件ですが、<br>1. char *p = "string";<br> ・char型へのポインタ変数pが定義される。<br> ・そのポインタ変数pは、書き込み不可領域に確保されている<br> 文字列リテラル"string"の先頭アドレスで初期化されている。<br><br>2. char a[] = "string";<br> ・char型の配列a(要素数7)が定義されている。<br> ・その配列aは、終端文字'\0'を含む7byteの文字列"string"で初期化されている。

まちゅ (2007-08-22 (水) 11:35)

なるほど、変更不可かそうでないかが違うんですね。(記憶は遥か彼方に…)<br><br>関数での値のやり取りとポインタは関連が深いですね。<br>ローカル変数は関数毎にスコープが分かれているという話からポインタの説明に入ると、ポインタの必然性を伝えやすそうです。

どぅ (2007-08-23 (木) 13:09)

Cのポインタは万能選手で、*演算子ひとつで、関数のスコープを超えて、プロセスに割り当てられたすべてのアドレスにアクセスできてしまいます。これを強力と見るか、強力過ぎると見るか。<br>その点javaのポインタ(参照)はお行儀が良いですが、今度はアホなプログラマがそれがポインタだということに気づかないままコーディングしてしまう恐れが・・・(昔のワタクシ^^;)

まーち (2008-03-19 (水) 02:23)

この辺の話題を替え歌にしたものがあります。「初音ミク」先生もCのポインタの教育には悩んでいるようですね。<br>http://www.nicovideo.jp/watch/sm2698774<br>いまどきの学生の様子が見て取れて面白いです