- <値型>と<参照型>、<値渡し>と<参照渡し>がそろってる言語で実行例を出す(C#)
- <値型>と<参照型>、<値渡し>と<参照渡し>がそろってる言語で実行例を出す(Swift編)
- <値型>と<参照型>、<値渡し>と<参照渡し>について実行例を出す(PHP編)
C言語に参照渡し(≠参照の値渡し)はない ですが、Cで同様のコードを表現してみました。参照渡しが裏でやっているのはこういうことだと理解しています。
実行コード
#include <stdio.h>
#include <stdlib.h>
typedef struct { int value; } ValWrap;
typedef ValWrap * RefWrap;
void swapAndEditValVal(ValWrap left, ValWrap right) {
ValWrap tmp = left;
left = right;
right = tmp;
tmp.value *= 100;
}
void swapAndEditRefVal(RefWrap left, RefWrap right) {
RefWrap tmp = left;
left = right;
right = tmp;
tmp->value *= 100;
}
void swapAndEditValRef(ValWrap *left, ValWrap *right) {
ValWrap tmp = *left;
*left = *right;
*right = tmp;
tmp.value *= 100;
}
void swapAndEditRefRef(RefWrap *left, RefWrap *right) {
RefWrap tmp = *left;
*left = *right;
*right = tmp;
tmp->value *= 100;
}
int main(int argc, const char * argv[]) {
{
printf("値の値渡し\n");
ValWrap left;
left.value = 1;
ValWrap right;
right.value = 2;
swapAndEditValVal(left, right);
printf("%d, %d\n", left.value, right.value);
}
{
printf("ポインタの値渡し≒参照の値渡し\n");
RefWrap left = malloc(sizeof(ValWrap));
left->value = 1;
RefWrap right = malloc(sizeof(ValWrap));
right->value = 2;
swapAndEditRefVal(left, right);
printf("%d, %d\n", left->value, right->value);
free(left);
free(right);
}
{
printf("値の参照渡しのようなもの(ポインタの値渡しを使って参照渡しの挙動を実装)\n");
ValWrap left;
left.value = 1;
ValWrap right;
right.value = 2;
swapAndEditValRef(&left, &right);
printf("%d, %d\n", left.value, right.value);
}
{
printf("参照の参照渡しのようなもの(前の二つの組み合わせで参照の参照渡しの挙動を実装)\n");
RefWrap left = malloc(sizeof(ValWrap));
left->value = 1;
RefWrap right = malloc(sizeof(ValWrap));
right->value = 2;
swapAndEditRefRef(&left, &right);
printf("%d, %d\n", left->value, right->value);
free(left);
free(right);
}
return 0;
}
実行結果
値の値渡し
1, 2
ポインタの値渡し≒参照の値渡し
100, 2
値の参照渡しのようなもの(ポインタの値渡しを使って参照渡しの挙動を実装)
2, 1
参照の参照渡しのようなもの(前の二つの組み合わせで参照の参照渡しの挙動を実装)
2, 100
雑感
Wikipediaの引数を読むと、 ポインタ渡し と ポインタの値渡し という言葉が出てきて両方同じ意味を表してるっぽいですが、ポインタ渡しという言葉は紛らわしいので良くないと思います。 参照渡し ≠ 参照の値渡し なのに、 ポインタ渡し = ポインタの値渡し というのはどう考えてもややこしいです。