C言語 値渡しとアドレス渡し

関数の引数に値を渡す場合、2つの方法があります。

値渡し

値渡しは、引数に数値を渡す、ごく普通の方法です。

#include <stdio.h>

int menseki(int teihen, int takasa);

void main(void) {

      int ans=0;
      int teihen=5;
      int takasa=10;

      ans = menseki(teihen, takasa);

      printf("面積=%d\n", ans);

}

int menseki(int x, int y) {

      return x * y / 2;
}
面積=25

この例では、menseki関数に実引数として
底辺5と高さ10を渡しています。

この5と10の値は、それぞれ、x、yに代入され、
menseki関数の処理を実行します。

ここで大切なのは、
x、yに代入された値を、仮に変更したとしても
変数teihenやtakasaの値は変わらないと言う事です。

関数内では仮引数とローカル変数の値しか変更できない
と言うのが普通です。

アドレス渡し

アドレス渡しは、ポインタ渡しとも言い、引数にアドレスを渡す方法です。

#include <stdio.h>

void menseki(int teihen, int takasa, int* p);

void main(void) {

      int ans = 0;

      menseki(5, 10, &ans);

      printf("面積=%d\n", ans);

}

void menseki(int teihen, int takasa, int* p) {

      p* = teihen * takasa / 2;
}

上の例では、menseki関数に実引数として
底辺5と高さ10とansのアドレスを渡しています。
面積を求めたら、ansのアドレスを使ってansに値を入れています。

関数内では仮引数とローカル変数の値しか変更できない
と言うのが、普通なんですが、値渡しの時と違い、
ポインタ機能を使って
関数外の変数ansの値を変更する事ができるのです。

スポンサーリンク

構造体を使った値渡しとアドレス渡し

#include <stdio.h>

struct hito {
    int age;
    char blood[3];
};

void show1(struct hito p);
void show2(struct hito* p);

void main(void) {

    struct hito tanaka;

    tanaka.age = 30;
    tanaka.blood[0] = 'A';
    tanaka.blood[1] = '\0';

    show1(tanaka);
    show2(&tanaka);

}

void show1(struct hito p) {

    printf("age = %d\n", p.age);
    printf("age = %s\n", p.blood);
}

void show2(struct hito* p) {

    printf("age = %d\n", p->age);
    printf("age = %s\n", p->blood);
}

上の例では、構造体を使い、
それぞれ値渡しとポインタ渡しを行っています。

show1関数の値渡しでは、
構造体のメンバageとbloodをshow1関数の仮引数pに代入し、
関数内の処理が行われます。
この場合、int型のageとchar型3つで
7バイト分の値渡しが行われる事になります。

そして、show2関数のアドレス渡しでは、
tanaka構造体のポインタをshow2関数の仮引数pに代入し、
関数内の処理が行われます。
この場合、ポインタ型なので、
4バイト分のアドレス渡しが行われた事になります。

構造体のメンバがどれだけ増えても
アドレス渡しを行えば、一律4バイトです。

このように、構造体を使う場合は、
値渡しよりもアドレス渡しの方が処理が軽くなるのです。

構造体のポインタ渡しは、
構造体のメンバが多くなればなる程、絶大な威力を発揮します。

関数へ構造体を渡す場合は、
極力、アドレス渡しを使うようにしましょう。

値渡しの特徴

値渡しのみの引数で構成された関数は、
その関数内の変数しか変更しませんので(グローバル変数は除く)、
他の関数に影響を及ぼす事がなく、
安心、安全で管理しやすい関数となります。

アドレス渡しの特徴

一方、アドレス渡しを使うと、
渡されたアドレスを使って関数外の変数も変更可能です。

便利ではありますが、他の関数にも影響を与えるので、
注意しながら使わなければなりません。