苦しんで覚えるC言語 15.7 配列とポインタの奇妙な関係 P313 – P320

配列のような使い方

前の章で引数とした配列は先頭要素のアドレスが渡されて、ポインタ変数の様な振る舞いをしていることを解説しました。

であれば、ポインタ変数で関数の引数を構成し、関数内の処理を描くことで多要素の変数に対して、読み書きが適うことになります。

具体的には以下の様な処理をベースに見てみましょう。

#include <stdio.h>

int getaverage(int *data);

int main(void)
{
    int average;
    int array[10] = {15,78,98,15,98,85,17,35,42,15};

    average = getaverage(array);
    printf("%d\n",average);

    return 0;
}

int getaverage(int *data)
{
    int i;
    int average = 0;

    for(i = 0; i < 10; i++)
    {
        average += data[i];  /* ポインタ変数なのに? */
    }

    return average / 10;
}

気になるのは具体的に以下の部分です。

average += data[i];  /* ポインタ変数なのに? */

dataは、int *data として引数で渡ってきます。
処理部では、data[i]として配列の様な書き方になっています。

参考書にも記載がありますが、配列の [ ] は要素を指定するために記載されるのですが、
「要素のアドレス番号を指定している」のと同じなのです。

その為、上記の様な書き方をしても問題はありませんが、一般的なエンジニアは、上記の様なコードの書き方をする方は少ないです。
どちらかと言えば以下の様な書き方をします。

data++;            /* ポインタ変数は、* がない場合、アドレスアクセスモードになる */
          /* アドレスを ++ で一つ先のアドレスに遷移となる */

average += *data;  /* ポインタ変数の中に格納されている値を取り出して加算 */

data++; でdata[0] ⇒ data[1]へ遷移しているのと同じです。
for文の中の処理を抜粋しているので、繰り返される度にdata[1] ⇒ data[2]・・・と、
次の要素のアドレスへ遷移をしていき、次行の *data; では、その時に遷移したアドレス番地に格納されている値を処理しています。

ポインタ専用の書き方

重複解説になりますが、ポインタ変数のアドレスへのアプローチは、配列の様な書き方をすることが少ないです。

先ほどは上記で、 data++; と書きました。
一つ先のアドレスをアクセスしたい場合は上記の書き方で良いですが、数個先のアドレスにアクセスしたい場合は以下の様に記載をします。

 ポインタ変数 + アクセス先の要素

例えば、data + 2; と書けば2つ先のアドレスにアクセスすることができます。
参考書では以下の書き方となっています。

 *(ポインタ変数 + アクセス先の要素)

意味は同じなのですが、四則演算と同様に ( ) が付いている方が先に処理されます。
その為、ポインタ変数にアクセス先の要素を加算(=アドレス処理モードで値を処理)してから、
* が付いた変数として処理(=指定アドレス内の格納された値を取り出すモード)で、値処理を行います。

どちらが分かりやすいかは、設計者によって分かれるところなので、
上記の書き方2種は、一般的にどちらも見受けられます。
ポインタ変数を使ってアドレス処理を行う場合、配列の様に [ ] を書かないのが一般的です。

参考書の筆者は、配列の様に [ ] を書いた方が分かりやすい。とされていますが、
設計経験をどのように積み上げたかによって、分かりやすいか否かは意見が異なるところです。

所属していた設計会社やプロジェクト規約で、配列の様な書き方を禁止されることがあれば、
筆者が分かりやすいと仰せの書き方は、馴染みがなく一般的ではないことになります。

配列の様なアクセスを避けるプロジェクト規約があるとすれば、
それは、ポインタアクセスなのか、通常の配列アクセスなのかが所見で識別できないので、
ダメだとされていると推測されます。

この辺りは、この後で実務を経験する際にご自身が分かりやすい流儀を確立していただければと思います。