言語は習うより慣れろ
ポインタはC/C++言語の特徴的な機能のひとつである。ポインタ(pointer)を直訳すると「指し示すもの」であり、別の変数や文字列定数の場所を指し示すために使う。また、ポインタを指すポインタ(ポインタへのポインタ)というものも存在する。
C/C++のポインタの機能--変数の場所(アドレス) - builder
ロジックの誤りはともかく、もう少し実践的な例題をあげた方が分かりやすくなるんじゃないでしょうか。ポインタとは何かじゃなくて、Cになぜそれが必要で、どんな時に使うと便利といった感じの説明があると、概念はおのずと理解できるような気がします。
そういえばポインタってどうやって覚えたんだっけ
yasuhoの場合、Cを学ぶ以前にPL/I系の言語でポインタを使っていたから、Cを見てもそんな違和感はなかったな。変数や型を間接的に指し示すもの、って感じ!?
ただ、Cはよりポインタを複雑に扱えるところがちょっと戸惑った。例えば
- charのポインタのポインタ
- short配列へのポインタの配列
- intを返す関数へのポインタの配列
とか、言葉で書くと「なんじゃそりゃ」なのがいっぱい。
そうだ、こうやって覚えたんだ
Cプログラムをコンパイルして、展開されたアセンブラリストを見たんだ。
例えばこんな感じ(Visual Studio 2005を使用)
- charのポインタのポインタ
int _tmain(int argc, char *argv[]) op = argv[0][1]; 0041387C mov eax,dword ptr [ebp+0Ch] ; argv 0041387F mov ecx,dword ptr [eax] 00413881 mov dl,byte ptr [ecx+1] 00413884 mov byte ptr [ebp-15h],dl
- short配列へのポインタの配列
short w[4]; short *paw[4]; w[0] = 1; 00413929 mov word ptr [ebp-34h],1 paw[0] = &w[0]; 00413929 lea eax,[ebp-34h] 0041392C mov dword ptr [ebp-4Ch],eax
- intを返す関数へのポインタの配列
typedef struct _OPS { char type; BOOL (*ops)(char *s, int *pv); } OPS, *POPS; OPS aOps[] = { { 'd', GetInt }, }; if (!aOps[i].ops(&argv[0][2], &v)) 004138D3 mov esi,esp 004138D5 lea eax,[ebp-0Ch] 004138D8 push eax ; &v 004138D9 mov ecx,dword ptr [ebp+0Ch] 004138DC mov edx,dword ptr [ecx] 004138DE add edx,2 004138E1 push edx ; &argv[0][2] 004138E2 mov eax,dword ptr [ebp-24h] 004138E5 mov ecx,dword ptr aOps+4 (417058h)[eax*8] 004138EC call ecx ; call (*ops)()
展開されたアセンブラコードを見ると、ポインタがどんなふうに実行されるのか確認できる。デバッガを使って実際に動きを追ってみるのも効果的だったな。
じゃあどうやって覚えるのがいいのかな?
今流行の言語だとこういうやり方は通用しないだろうね。ただ、個人的に言語を覚える方法として有効だと思う方法はとにかくいろいろ使ってみることじゃないかな。
もちろんドキュメントを読んだりして体系的に覚えることも大事だと思う。けど、言語に限らずコンピュータ関連技術はやってみないと分からない、あるいは使ってみた方が理解できることがとても多い。むしろ、使ってみて初めて身につくと言った方がいいかも。
それは単にプログラムの理解というだけにとどまらなくて「これはどうやって実現しているんだろう」という探求心にもつながっていくと思う。ソースコードを見ることで、さらにその先の技術へというように、知識と経験の幅を広げていくものじゃないかなあ。
まーyasuhoの場合、ドキュメント読むのが不得意ということの言い訳かもしれないけどさ。^^;
[4/8/2008 追記]
参照先の記事へのリンクを入れ忘れてました。最初を読むと何のことか分からないですよね。^^;