C言語とJavaのコードで見るポインタと値渡し

267, 2019-12-25

目次

C の値渡し

C では全て値渡しで実現される。変数が持つアドレスも値渡し(コピー)される。

void f1(int arg) {}
void f2(int* ptr) {}

int num = 0;
f1(num);
f2(&num);

変数 num の値は、f1 では仮引数 arg にコピーされる。
変数 num のアドレスは、f2 では仮引数のポインタ変数 ptr にコピーされる。

肝心なのが f2 で、ポインタ変数 ptr を使ってメモリにアクセスすると

*ptr = 10;

変数 num の値も変わる。
ポインタ変数 ptr に違うポインタを代入しても

ptr = NULL;

ポインタ変数 ptr の持つアドレスはコピーされたものだから、変数 num のアドレスには影響がない。

Java の参照値の値渡し

こちらによると、Java では参照値を値渡しするらしい。

public void f(ArrayList<String> arg) {}

ArrayList<String> list = new ArrayList<String>();
list.add("A");
f(list);

オブジェクト list の参照値は、仮引数 arg にコピーされる。
参照値からメモリ上のオブジェクトへアクセスすると

arg.add("B");

オブジェクト list の値も変わる。
仮引数 arg に違うオブジェクトへの参照値を代入しても

arg = new ArrayList<String>();

arg の参照値はコピーされたものだから、list に影響はない。

比較

#include <stdio.h>
#include <stdlib.h>

void f(int* ptr) {
    *ptr = 10;

    ptr = (int*) calloc(1, sizeof(int));
    *ptr = 12345;

    printf("f: ptr value is %d\n", *ptr); // f: ptr value is 12345
    // free(ptr); // YES, MEMORY LEAK.
}

int main(void) {
    int* ptr = (int*) calloc(1, sizeof(int));

    f(ptr);
    printf("main: ptr value is %d\n", *ptr); // main: ptr value is 10

    free(ptr);
    return 0;
}
import java.io.*;
import java.util.*;

public class Main {
    public static void f(ArrayList<String> list) {
        list.add("B");

        list = new ArrayList<String>();
        list.add("don't touch me!");
        System.out.println("f: list is '"+ list +"'"); // f: list is '[don't touch me!]'
    }

    public static void main(String args[]) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("A");

        f(list);
        System.out.println("main: list is '"+ list +"'"); // main: list is '[A, B]'
    }
}

Java の String

Oracle のここを見ると、String にはメモリを新しく確保するメソッドが並んでいるように見える。Java の String はイミュータブルなオブジェクトなのでこういう設計になるらしい。参照値が指す値を変更したかったが、どれを使えばいいのかわからんちんなわたし。

public static void f2(String arg) {
    arg = new String("don't touch me!?");
}

public static void main(String args[]) {
    String str = new String("A");
    f2(str);
    System.out.println("main: str is '"+ str + "'"); // main: str is 'A'
}

おわりに

Java のオブジェクトは C のポインタみたいな挙動をする。

Webアプリケーションの制作ならNARUPORT

Webアプリケーションの制作ならNARUPORTにお任せください。
Webアプリの他にもGUIアプリやChromeExtension, スクリプトの制作など可能です。
以下のお問い合わせフォームからご依頼ください!

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク