配列の参照渡し


以前習ったように(文字列を含む)配列の変数名を単独で(添え字を付けずに)使うと、配列の先頭のアドレスを意味する。

#include <stdio.h>

int main() {
  int numbers[] = {5,10,15,20};
  printf("&numbers[0]: %p\n", &numbers[0]);
  printf("    numbers: %p\n", numbers);
}

実行結果の例:

&numbers[0]: 0x7ffd2a2f2370
    numbers: 0x7ffd2a2f2370

ようするに、関数名(配列名, ...) のように配列を引数として関数に渡す場合は、配列の中身がコピーされるのではなく常にアドレスを用いた参照渡しになる(関数中の配列名が違うだけで、元の配列と同じデータを参照している)。したがって、関数の中で配列の中身を変更すれば、元の(呼び出し側)の配列にもその変化が反映される。

例:

#include <stdio.h>

void update_arr(int arr[], int id, int val) {
  arr[id] = val;
}

int main() {
  int numbers[4] = {0,10,20,30};
  printf("呼び出し前の numbers[0] の値: %d\n", numbers[0]);
  update_arr(numbers, 0, 5);
  printf("呼び出し後の numbers[0] の値: %d\n", numbers[0]);
}

実行結果:

呼び出し前の numbers[0] の値: 0
呼び出し後の numbers[0] の値: 5

文字列を使った例:

#include <stdio.h>
#include <string.h>

void query(char msg[], char buf[], int len) {
  printf("%s", msg);      /* 引数として受け取ったメッセージを表示 */
  fgets(buf, len, stdin);  /* 標準入力からの読み込み */
  if ('\n' == buf[strlen(buf)-1]) {
    buf[strlen(buf)-1] = '\0';  /* 改行を削除 */
  }
}

int main() {
  char name[100];
  query("あなたの名前は?: ", name, sizeof name);
  printf("あなたは %s ですね\n", name);
}

実行結果の例:

あなたの名前は?: Tarou
あなたは Tarou ですね

配列を受ける関数の仮引数の書き方は2つある(意味は同じ):

型 配列名[]

(例:void my_func(int arr[])

または

*配列名

(例:void my_func(int *arr)


目次