ポインタ(序論)


なぜ、ポインタを使うのか?

 本題に入る前に、余談です。C言語のプログラミングスタイルについてですが、あるデータがあったときにそのデータを加工するなり、計算するなりして、画面上に出力、ファイルに保存などをしていく処理の単位は、C言語では紛れもなく関数です。自分が目的とする機能を実現するために順を追って関数を作っていくと思います。だから、main() の関数の中に何十行もの処理を書いて "はいおしまい" っていうのはC言語らしいプログラミングスタイルではありません。データがあったらそれを関数に渡して処理していくのがC言語らしいスタイルだと思われます。

 そこで、関数にデータを渡すとき、2通りの考え方があります。データをそっくりそのままコピーして伝えるのか、データがメモリ上のどこにあるのかを伝えるのか。関数の呼び出し元で前者と後者は場合によっては全く違う結果を得ます。例えば、ある合計金額に消費税を追加する関数を作ったとします。addTax とでもしましょう。前者の場合、コピーをしただけなので関数の呼び出し元では、その関数の前後で、金額は変更されません。コピーだからメモリ上で別々の空間に保存されているからです。コピーした方は変わりますが、コピーされた方は影響を受けません。一方、後者では addTax を呼び出した関数内と、addTax の関数内で同じメモリ位置に対して計算処理が出来るので addTax 内での変更が addTax 関数の呼び出しもとの前後で、有効になります。下にC言語もどきの例を挙げます。

<前者>
void addTax( 金額のコピー ) /* 引数はコピーなので基ネタとは別のメモリ空間 */
{
    消費税を金額のコピーに加える;
}

void main( void )
{
    a = 1000円;
    /* この位置で変数 a は当然、1000円 */
    addTax( aの値 ); /* a のコピーに消費税を加える */
    /* コピーに消費税が加えられたので、基の a は変更されない */
    /* この位置でもやっぱり変数 a は1000円 */
}

<後者>
void addTax( 金額データのある場所 ){ /* 基と同じメモリ空間に対して処理が出来る */
{
    金額データのある場所より、基のメモリ位置の値に消費税を加える;
}

void main( void )

{
    a = 1000円;
    /* この位置で変数 a は当然、1000円 */
    addTax( aの場所 ); /* a メモリ空間内での位置を参考に、消費税を加える */
    /* メモリ空間内での位置を参考に消費税を加えたので、基の a は変更されている */
    /* この位置では変数 a は1000円+消費税 */
}

 例は、分かっていただけたでしょうか? 要するに後者では関数呼び出し元の金額データがある場所が addTax 内でも分かるので、その呼び出し元の金額データに直接、消費税を加えることが出来ます。一方、前者はコピーされたデータが単に値としてくるだけなので、 addTax 内では呼び出し元での金額データがメモリ上のどこにあるのか分かりません。よって、関数の呼び出し元で、金額データに addTax 内での処理が反映されないわけです。わかりました?

 この、「データの位置」がポインタ(指すもの)です。C言語ではポインタを使って、関数間のデータのやりとりを行うことによって、ある関数内での変更(addTax内での消費税の追加)をその関数の呼び出し元の、基の変数(基の金額、1000円ですね)に反映することが出来ます。(データの場所を渡しますから)また、これにより、関数間でやりとりするデータが大きくなった時、例えば、大きな配列や構造体になったときも、コピーをして関数間でデータのやりとりをせず、「メモリ上のこの位置にデータがあるよ」という、情報をやりとりするので、引数のコピーに要するオーバーヘッド(この場合、メモリ間のデータコピー)を軽減することも出来るわけです。だから、ポインタを関数から関数に渡してデータを加工していくのがC言語のスタイルです。addTax の戻り値は型無し(void)としましたが、戻り値に「消費税を加えた金額」とすることもできますが、あまり、しないとおもいます・・・。引数が無効、例えばマイナス(金額としてマイナスはおかしい)の値だったら、 False を返すと言うような使い方をする事はありますが、これも関数呼び出し前にチェックすれば不要な機能ですね・・・。

 以上、何故ポインタを使うのか、と言うことは分かっていただけたでしょうか?これで、序論はおしまいです。次に、実際のソースコードを使って、動作を確かめたいと思います。


ポインタ(序論、サンプルコード)

C言語講座トップページ

TOP-PAGE

Web-Page制作者e-mailアドレス