【独学C言語入門㉘】値渡しとポインタ渡し

今回はかなり難易度が高いのでポインタを十分理解されてから読まれることをお勧めします。関数に引数として変数を渡す時には「値渡し」と「ポインタ渡し」の2種類があります。ポインタ渡しは厳密には異なりますが「参照渡し」と呼ばれることもあります。まずは次のイメージと表でご説明します。

【値渡しのイメージ】
①1番地に太郎さんが住んでいた
②2番地に同姓同名の太郎さんが引っ越してきた
③2番地の太郎さんの名義が次郎さんに変わった(1番地の太郎さんは住み続けている)

名義太郎(x)太郎(a=x)次郎(a=y)
住所1番地(&x)2番地(&a)2番地(&a)

【ポインタ渡しのイメージ】
①1番地に太郎さんが住んでいた
②1番地の名義が太郎さんから次郎さんに書き換えられた
(1番地は次郎さんが住むことになった)

名義太郎(x)次郎(y)
住所1番地(&x)

値だけ関数に渡すのが値渡し、アドレスを関数に渡すのをポインタ渡しと呼びます。先述の通り、値渡しは値をコピー(x = a)しますが元のxと新しく作ったaは別に管理されます。それに対してポインタ渡しはアドレスを渡すので元の変数が書き換えられます。

実際の動作で2つの渡し方の違いを体感してもらいます。値渡しとポインタ渡しで引数を渡し、関数内ではもらった引数に5を代入して結果を比較します。

#include <stdio.h>

void value(int a);    //値渡し
void pointer(int *a); //ポインタ渡し

main()
{
   int x = 2;

   printf("a=%d\n", x);

   value(x);  //値を渡す
   printf("a=%d\n", x);
    
   pointer(&x); //アドレスを渡す
   printf("a=%d\n", x);
}

//値渡し確認用関数
void value(int a)
{
    a = 5;  //引数に5を代入
}

//ポインタ渡し確認用関数
void pointer(int *a)
{
//そのアドレスに格納されている
//値に5を代入
    *a = 5; 
}

//右が切れたら左にスワイプしてください

初めて見られた方は意味不明かもしれません。2つの関数内で引数に5を代入しましたが、値渡しでは元のxが書き変わらず、ポインタ渡しではxが書き換えられていますね。

値渡しでは新たにaという変数を作ってxの値だけをコピーしているため関数内でaを書き換えても元のxには全く影響を与えません。

しかし、ポインタ渡しはxのアドレスを渡すため&xとa(ポインタ)は全く同じアドレスになります。そのため*aを書き換えられるとxの値も変更されてしまいます。

C言語でポインタ渡しは多くの方が挫折するポイントですが、混乱しそうになったら最初の2つの表をじっと見てもらえればと思います。ポインタで悩みそうになったら、紙にポインタとその値を1度書いて落ち着いてもらうと理解しやすいかと思います。

独学C言語入門一覧に戻る