C言語入門(12) ポインターはいつ使うべきなのか

Posted: 2012年07月16日

いままでは、ポインターとは何かやポインタの宣言の仕方を書きましたが
今回は、ポインターの使用方法を書きます。

具体的には、
一般的にどの場合に使用するか、その場合どの利点があるか
ということです。

配列のアクセス

配列のデータを参照して計算を行う処理など
ポインターを用いることで完結に記述できます。

プログラムプログラム:

int aryExamPoint[32]; // テストの点数(32人)
int naryIndex = 0;
int navgPoint = 0;
int naryCount = sizeof(aryExamPoint);
// 平均点を求める
for (naryIndex = 0; naryIndex < naryCount; naryIndex++)
{
    navgPoint += aryExamPoint[naryIndex];
}
navgPoint /= naryCount;
int aryExamPoint[32 + 1]; // テストの点数(32人)
int *paryExamPoint = aryExamPoint;
int navgPoint = 0;
int naryCount = sizeof(aryExamPoint);
aryExamPoint[naryCount] = -1;
// 平均点を求める
while (0 <= *paryExamPoint)
{
    navgPoint += *paryExamPoint;
    paryExamPoint++;
}
navgPoint /= naryCount;

解説解説:

どちらもテストの平均点を求めるプログラムです。
前提条件として配列には、点数が設定されている
ポインターを用いた方では、配列をひとつ増やし、配列の終わりだとわかるように(-1)を入れています。(番兵といいます)
通常の配列でアクセスでも同じように番兵を用いて計算することは可能です。
ポインターを用いることの利点は、
配列のデータにアクセスする計算がひとつ不要になった点

通常の配列のアクセス
naryIndexを計算→配列からnaryIndexの位置を計算→データを取得
ポインターを用いた配列のアクセス
paryExamPointを計算→データの取得

なぜ、不要になったかと言いますとポインターは、常に配列の取得したい要素の位置が入っているためです。
ポインターを用いることの欠点は、
可読性が落ちたことです。

パフォーマンスを重視する場合はポインターを使用したほうがいいとは一概に言えず
この場合では、通常の配列のアクセスでもコンパイラーのおかげで同様の処理に書き換えられると思われます。
どうしてもパフォーマンスが必要と思った時のみに、この方法を行えばいいと思います。

関数の引数

標準関数でも引数にポインターを受け取ることがあるため
よく馴染みがあるけど、あまり把握せずに使っている場合があったりします。
関数の引数でポインターを使うことで、無駄なメモリーの使用を抑えるやデータの戻り値として使用することができます。
関数の引数に設定されたデータは、コピーされるため巨大なデータを渡す場合は、
ポインターで渡すことで実データのコピーはされないため、メモリーを無駄に消費しません。

関数の戻り値として使用する場合の例

プログラムプログラム:

 #include  <stdio.h>
 #include  <math.h>

 BOOL AddNumber(int nA, int nB, int *pnResult)
 {
     *pnResult = nA + nB;
     return TRUE;
 }

 int main(void)
 {
     int nResult;
     if (AddNumber(4, 6, &nResult) == FALSE) {
         return -1;
     }

     return 0;
 }

解説解説:

数値を足し算する関数を定義しました。
この関数は、戻り値に成功したかを返します。(BOOL)
引数pnReultに足し算結果を返す。
この動作は、標準関数のScanfとほぼ同様の形です。

&nResultでnResultのポインターを渡し、関数でそのポインター先にデータを設定してもらう処理の流れです。
処理の成功結果以外にも、複数の戻り値を返したい場合などでも使用します。

今回はここまでで次回は、この続きを書きます。

カテゴリー: プログラム, 入門 | タグ: , | コメント無し »

コメント