C言語の学習において、ポインタはよく躓くポイントとして知られています。「Javaにポインタはない」などと表現されることがありますが、実際にポインタは存在します。 NullPointerExceptionという例外が存在することからもこれは窺えるのですが、 C言語のポインタとはちょっと違っており、名前も「参照」と改められています。
C言語のポインタが果たす3つの役割
C言語ではポインタには3つの役割がありました。
- 変数や構造体を指し示すもの
- 配列を表現するもの
- 関数を指し示すもの
これらが渾然一体となって、コンピュータの低レベルな「アドレス」という値になって扱われるのです。これがC言語でポインタを理解することを難しくしているのではないでしょうか。
Javaではどのように置き換えるのか?
Javaではこれらの3つの機能は明確に分離されています。
まず、変数や構造体を「指し示すもの」としては「参照」という名のポインタが使われます。 C言語で構造体で表されたデータの塊というのは、Javaではクラスによって表現します。このクラスへの「参照」はポインタをより抽象化したもので、ポインタ演算を行うことは出来ません。
次に配列。C言語では配列の[]はポインタ演算のシンタックスシュガーでしたが、 Javaでは配列は明確な地位を得ており、配列を扱う際は[]による操作しか許されません。
C言語ではこれらの区別をしないため、配列に対してはポインタ演算を行ってよく、配列ではない単一の構造体へのポインタに対しては行ってはいけないといったように、似て非なる機能性が混在するため、混乱無く正しく理解するには訓練を要します。
Javaの場合は、これらをあらかじめまったく別の機能性として表現しており、 ポインタ演算、つまり配列としての機能性は配列のみに有効になるようにしています。また、配列へのアクセスはC言語ではシンタックスシュガーであった[]によるアクセスのみとなっており、理解しやすいのでしょう。(理解しやすいからこそC言語で[]がシンタックスシュガーとして取り入れられているとも言える)
関数ポインタへの対応
C言語でも関数ポインタは配列などとは別物として扱われるので、あまり混乱しないように思われます。
Javaで関数ポインタのようなものを扱いたい場合は、通常interfaceを用いてメソッドの型を定義し、関数ポインタの変わりに、その実装クラスのインスタンスを渡すようにします。
結論
C言語においては「アドレス」というコンピュータの低レベルな概念が出てきますが、 Javaでは「アドレス」については意識しません。そのため、「指し示すもの」としてのポインタの機能性のみに集中して理解することが出来るのではないでしょうか。
また、配列としての機能性と、「指し示すもの」としての機能性を分離することでポインタ演算に対して適用範囲を明確化することで理解を容易にしているのではないでしょうか。
C言語のポインタの解説ではメモリというものが必ず出てきますが、概念としてのポインタを理解するにはメモリという実体は一旦置いておいた方がいいのかもしれません。 JavaやC#などから入ってC言語を学習するほうがポインタに対しての壁は低いかもしれませんね。
投稿日時 : 2007年12月5日 16:18