C言語では、関数の引数で「配列そのもの」を受け取ることができない。配列の先頭のアドレスを受け渡すことになる。
だから、配列の要素数は別途引数を用意して受け渡さなければならない。そうでないと関数内で配列の要素数を知るすべがなく、困ってしまう。
int sum_all(int length, int arr[]) {
/* int sum_all(int length, int *arr) でも同じ意味になる */
int i, result = 0;
for (i = 0, i < length; ++i) {
result += arr[i];
}
return result;
}
ところで、二次元配列の事を考えてみる。多次元配列の場合、要素数の省略は最初の[]にしかできないから、普通にやるとこんな感じになってしまう。
/* 2次元のint配列を受け取って、全部足して返す */
int sum_all2(int xlength, int arr[][3]) {
int i, j, result = 0;
for (i = 0; i < xlength; ++i) {
for (j = 0; j < 3; ++j) {
result += arr[i][j];
}
}
return result;
}
\突然現れるマジックナンバー3!/
これだと、要素数が片側固定になってしまうので関数の使い心地が悪い。一次元配列のintポインタにキャストしてarrを渡すという技もあるけど、素直じゃないし、書き方がポインタ演算になってしまうのでわかりにくくなっちゃう。
とか悩んでたら、C99だとこんな書き方ができるんだそうな。
int sum_all2(int size1, int size2, int arr[size1][size2]) {
int i, j, result = 0;
for (i = 0; i < size1, ++i) {
for (j = 0; j < size2, ++j) {
result += arr[i][j];
}
}
return result;
}
int main(void) {
int arr[][3] = {{1,2,3}, {4,5,6}, {7,8,9}};
printf("%d", sum_all2(3, 3, arr));
return EXIT_SUCCESS;
}
仮引数って引数宣言の中で使えるようになるんですね。。
これなら、配列サイズに依存せずに使えるし、書き方もそんなに気持ち悪くないし、便利。