C言語

関数にポインタ型の引数を渡す

引数を使ってデータを渡す関数の使い方」で、引数を使用した関数について学びました。このときは、変数や数値のみでしたが、今回は、ポインタ型や配列を引数で渡すことについて学びます。
基本的には、前に学んだ普通の引数と変わりはありませんが、ポインタ変数という性質上の違いがありますので、違いについて触れたいと思います。

普通の引数とポインタ型の引数の違い

C言語では、関数へデータを渡す場合に引数を使って値を渡します。このとき、実引数(呼び出し元の引数)に変数を指定していても、関数へ渡すデータは、変数ではなく、変数に格納されている値のみが渡されることになっています。このような渡し方を値渡しといいます。つまり、関数の呼び出し元の引数で指定した変数と、関数の仮引数に定義した変数は別の変数ということになります。このため、関数内で値を変更しても呼び出し元の変数は変更されません。

ポインタ型の引数でも、基本的に値渡しと同じです。ただし、ポインタ型の引数は、渡される値がアドレスとなっているため、 関数の呼び出し元の引数で指定した変数と、関数の仮引数に定義した変数は別の変数でも、アドレスを受け取ることができるため、実引数と仮引数が同じアドレスを示すことになります。そして、このアドレスの値を、呼び出した関数内で変更すれば、呼び出し元で引数に指定した変数の値も変わることになります。
このように、実引数の変数のアドレスが関数に渡されることを参照渡しと呼んでいます。

参照渡しをするサンプルプログラムを次に示します。

#include <stdio.h>

void pointerfunc(int num1, int *num);

int main(void)
{
    int num1 = 1;
    int num2 = 2;
    pointerfunc(num1, &num2);
    printf("num1=%d, num2=%d\n", num1, num2);
    return 0;
}

void pointerfunc(int num1, int *num)
{
    printf("num1=%d, num2=%d\n", num1, *num);
    num1 = 11;
    *num = 12;
}

main関数でnum1とnum2を初期化した値をpointerfunc関数に渡しています。このとき、num1は値渡し、num2は参照渡しです。
pointerfunc関数では、渡された値を表示してから、2つの引数の値を更新しています。
pointerfunc関数を実行後、main関数に戻って、num1とnum2の値を確認します。このとき、num1は値渡しをしているので、pointerfunc関数で値を更新しても、main関数のnum1変数に影響はありません。
num2は、参照渡しをしているため、pointerfunc関数で更新された値になっていることが確認できると思います。

サンプルプログラムを実行した結果は次のようになります。

実行結果

num1=1, num2=2
num1=1, num2=12

num1は、値渡しのため、main関数のnum1変数と、pointerfunc関数のnum1変数とは別物なので、pointerfunc関数内でnum1を更新してもmain関数には影響がないため、num1の結果はかわりません。
num2は、参照渡しのため、main関数のnum2変数と、pointerfunc関数のnum変数は同じアドレスを示しているため、pointerfunc関数内でnum変数を更新すると、main関数のnum2変数の値がかわります。
このため、pointerfunc関数内でnum変数を更新したときに、main関数のnum2変数のアドレスと同じなので、num2変数の値も変わったことを示しています。

関数にポインタ型の引数を渡した場合の動作は以上です。

次は、複数のファイルに分割するやり方について学びます。

ソースコードを複数のファイルに分割

-C言語