C言語で関数に足算したアドレスを渡しているときに Java はどうすりゃええねん. という話

2023-05-08 更新

例えば

C 言語 (C++ でもいいよ) でこういう処理があったとする

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#define arrayLength 10
#define shiftWidth 2
#define incLength 3
void elementChange(int *a);

int main(void) {
    int a[arrayLength] = {0};

    // ここで指定された配列の要素のみを変更する
    elementChange(a + shiftWidth);

    // 配列の中身を表示
    for(int i=0; i<arrayLength; i++)
        printf("%d ", a[i]);
    printf("\n");

    return 0;
}

void elementChange(int* a)
{
    for(int i=0; i<incLength; i++) a[i]++;
}
1
2
3
$ gcc-12 main.c -o cmain.out
$ ./cmain.out
0 0 1 1 1 0 0 0 0 0 

これはなにをしているかというと

  • 配列の先頭要素から incLength の長さだけインクリメントする elementChange 関数に
  • a 配列の先頭アドレスから shiftWidth だけズラしたアドレスを渡すことで
  • elementChange からすると a[shiftWidth] 先頭要素に見えるので
  • a[shiftWidth] から a[shiftWidth + incLength] がインクリメントされる   という処理である. ややこしいね.

これを Java で実現したい

Java は賢いのでプログラマにポインタを触らせてくれません. なので (当然) コピペだと動かないんですよね.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main {
    static final int arrayLength = 10;
    static final int shiftWidth = 2;
    static final int incLength = 3;

    public static void main(String[] args) {
        int[] a = new int[arrayLength];

        // ここで指定された配列の要素のみを変更する
        elementChange(a + shiftWidth);

        // 配列の中身を表示
        for(int i=0; i<arrayLength; ++i)
            System.out.printf("%d ", a[i]);
        System.out.printf("\n");
    }

    private static void elementChange(int[] a)
    {
        for(int i=0; i<incLength; ++i) a[i]++;
    }
}
1
2
3
4
5
6
7
$ javac Main.java
Main.java:8: エラー: 二項演算子'+'のオペランド型が不正です
        elementChange(a + shiftWidth);
                        ^
  最初の型: int[]
  2番目の型: int
エラー1個

で, これを頑張って (Java 歴半年未満が) elementChange の中身に手を付けず動かそうとした結果がこちら.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.Arrays;

public class Main {
    static final int arrayLength = 10;
    static final int shiftWidth = 2;
    static final int incLength = 3;

    public static void main(String[] args) {
        int[] a = new int[arrayLength];

        // ここで指定された配列の要素のみを変更する
        int[] aSlice = Arrays.copyOfRange(a, shiftWidth, a.length);
        elementChange(aSlice);
        System.arraycopy(aSlice, 0, a, shiftWidth, aSlice.length);

        // 配列の中身を表示
        for(int i=0; i<arrayLength; i++)
            System.out.printf("%d ", a[i]);
        System.out.printf("\n");
    }

    private static void elementChange(int[] a)
    {
        for(int i=0; i<incLength; i++) a[i]++;
    }
}
1
2
$ java Main.java
0 0 1 1 1 0 0 0 0 0 

一回スライスしてから関数に投げることで解決, やったあ!

[ARTICLE: CC BY 4.0] [CODE BLOCK: CC0]
Built with Hugo
テーマ StackJimmy によって設計されています。