見出し画像

【C言語】ポインタ ~ポインタを使って関数から情報を取得してみる ~

前回、ポインタの概要について説明してみました。

では、ポインタはどんな風に使うのでしょうか。

「関数の引数」です。

こんな関数を考えてみましょう。

「2つの変数を足し算する関数」
(ありがちだなぁ(苦笑))

引数は2つ。
足し算した結果は戻り値で返しましょうか。
こんな感じです。

int add(int a, int b)
{
       return (a + b);
}

これは、ポインタはいりませんね。

では、四則演算を全部やっつけて、全部の結果を返す関数を考えてみましょう。
(そんな関数いるか?、というツッコミは却下)

ああ。
でも、4つもの値をどうやって返せばいいんでしょう。
戻り値は1つしか返せません。

4つの結果を入れる変数を用意してそのアドレスを渡してもらえばいいのです。
そうすれば、そのアドレスに結果を設定してあげることができます。

ここで「ポインタ」の登場です。
「アドレス」を「ポインタ変数」として受け取ります。

こんな感じ。

void four_cal(
        int a,
        int b,
        int* padd,
        int* psub,
        int* pmul,
        int* pdiv
)
{
        *padd = a + b;
        *psub = a - b;
        *pmul = a * b;
        *pdiv = a / b;
        return;
}

足し算、引き算、掛け算、割り算の結果を、*padd、*psub、*pmul、*pdivに設定することで、呼び出した関数に結果を返します。

この関数、どうやって使うのでしょうか。
アドレスを渡せばいいんだけど。

まず、間違ってもこんな書き方はいけません。

        int* padd;
        int* psub;
        int* pmul;
        int* pdiv;
        four_cal(10, 2, padd, psub, pmul, pdiv);

引数に渡す「型」はあってるんだけど、初期化されていないですね。
「初期化されていないポインタ」変数というのは、言い換えれば「デタラメなアドレス」ということになります。
デタラメなアドレスのメモリをアクセスしてはいけません。
コンピュータをぐちゃぐちゃにしてしまいます。

では、これは?

        int* padd = (int*)0;
        int* psub = (int*)0;
        int* pmul = (int*)0;
        int* pdiv = (int*)0;
        four_cal(10, 2, padd, psub, pmul, pdiv);

これもダメです。
初期化すればなんでもいい、というわけではありません。
きっちりと、使ってもいいアドレスを設定しなければいけません。

「int」型の変数を用意して、そのアドレスを設定してあげましょう。

        int add;
        int sub;
        int mul;
        int div;
        int* padd = &add;
        int* psub = ⊂
        int* pmul = &mul;
        int* pdiv = ÷
        four_cal(10, 2, padd, psub, pmul, pdiv);

でも、これはちょっと煩わしいですね。
こんな風に書けます。

        int add;
        int sub;
        int mul;
        int div;
        four_cal(10, 2, &add, &sub, &mul, &div);

こうすれば、add、sub、mul、divに、足し算、引き算、掛け算、割り算の結果を入れてもらえます。

int main()
{
        int add;
        int sub;
        int mul;
        int div;
        four_cal(10, 2, &add, &sub, &mul, &div);
        return 0;
}

void four_cal(
        int a,
        int b,
        int* padd,
        int* psub,
        int* pmul,
        int* pdiv
)
{
        *padd = a + b;
        *psub = a - b;
        *pmul = a * b;
        *pdiv = a / b;
        return;
}

どういうことがおこっているのでしょうか。
図で説明してみましょう。

関数「main」は、add、sub、mul、divの4つの変数を用意します。

関数「four_cal」を呼び出すとき、4つの引数にこのアドレスを渡します。

関数「four_cal」は、4つの引数をポインタ変数として受け取ります。

関数「four_cal」は、4つの引数に「*」をつけてアクセスすれば、関数「main」が用意した4つの変数にアクセスすることができます。

関数「main」に戻ってくれば、4つの変数に結果が入っていることになります。

あれ?
なんだ簡単じゃん。

そう、それだけなんだけど。

間接参照って、ちょっとややこしいかもしれない。
「padd」は
「padd」

「*padd」
の2ヵ所にアクセスできるわけで、それがちょっと混乱させるかもしれません。

あと気になる問題は、次のものだろうか。
・配列との関係
・ポインタの演算(+1したらどうなる?)
・ポインタのキャスト

それも順に書いてみましょうか。

次回以降に・・・。

この記事が気に入ったらサポートをしてみませんか?