ここでは、配列を関数の引数として扱う場合の細かい説明をしてみます。
1次元配列 1.配列をポインタ変数で受け取って使う 2.引数の要素数の省略 2次元配列 1.引数の要素数の省略 2.配列をポインタ変数で受け取って使う
まず1次元配列の話から始めましょう。
本編で作成したプログラムを書きます。
<sample program 139-01>
#include <stdio.h> #define DATA 5 void ShowArray(int data[DATA]); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int data[DATA]) { int i; for (i = 0; i < DATA; i++) { printf("%3d", data[i]); } printf("\n"); } |
<実行結果>
3 6 9 12 15 続行するには何かキーを押してください・・・
このプログラムは↓のように書くことも出来ると説明しました。
<sample program 139-05>
#include <stdio.h> #define DATA 5 void ShowArray(int *pData); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int *pData) { int i; for (i = 0; i < DATA; i++) { printf("%3d", pData[i]); } printf("\n"); } |
<実行結果>
3 6 9 12 15 続行するには何かキーを押してください・・・
配列の先頭のアドレスを渡しているので、ポインタ変数で受け取ることが出来るということでした。
ポインタ変数は、本文の中で「*」を付けることによりアドレスが指している中身を扱うことが出来ます。
そこで、次のようにプログラムを変更して実際に動かしてみてください。
<sample program col033-01>
#include <stdio.h> #define DATA 5 void ShowArray(int *pData); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int *pData) { printf("%d\n", *pData); } |
ポインタ変数「pData」は配列の先頭のアドレスを受け取っています。
「pData」の前に「*」を付けることにより、先頭のアドレスの中身が表示されます。
実行結果は何でしたか?
<実行結果>
3 続行するには何かキーを押してください・・・
配列の先頭の要素に入っている「3」が表示されました。
また、ポインタ変数は+1することで次のデータが入っているアドレスを指すとも説明しました。
そこで、次のようにプログラムを変更してみましょう。
<sample program col033-02>
#include <stdio.h> #define DATA 5 void ShowArray(int *pData); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int *pData) { printf("%d\n", *(pData + 1)); } |
受け取った先頭アドレスに1を加算し、中身を表示するようにしました。
何が表示されましたか?
<実行結果>
6 続行するには何かキーを押してください・・・
配列の2番目のデータ「6」が表示されました。
ということは、配列のデータ全てを表示するプログラムは次のように書き換えることも出来るということです。
<sample program col033-03>
#include <stdio.h> #define DATA 5 void ShowArray(int *pData); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int *pData) { int i; for (i = 0; i < DATA; i++) { printf("%3d", *(pData + i)); } printf("\n"); } |
<実行結果>
3 6 9 12 15 続行するには何かキーを押してください・・・
次に引数の要素数を省略する方法を書きます。
また以前のプログラムを題材にします。
<sample program 139-01>
#include <stdio.h> #define DATA 5 void ShowArray(int data[DATA]); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int data[DATA]) { int i; for (i = 0; i < DATA; i++) { printf("%3d", data[i]); } printf("\n"); } |
<実行結果>
3 6 9 12 15 続行するには何かキーを押してください・・・
この関数の引数に要素数「DATA」が入っていますが、これを省略して書くことが出来ます。
<sample program col033-04>
#include <stdio.h> #define DATA 5 void ShowArray(int data[]); int main(void) { int data[DATA] = { 3, 6, 9, 12, 15 }; ShowArray(data); return 0; } void ShowArray(int data[]) { int i; for (i = 0; i < DATA; i++) { printf("%3d", data[i]); } printf("\n"); } |
<実行結果>
3 6 9 12 15 続行するには何かキーを押してください・・・
結局、先頭アドレスを渡しているので要素数は重要では無いということです。
これで、1次元配列の渡し方は3通りになりました。
/* 配列(要素数あり) */ void ShowArray(int data[DATA]); |
/* 配列(要素数無し) */ void ShowArray(int data[]); |
/* ポインタ変数 */ void ShowArray(int *pData); |
以前、個人的には
void ShowArray(int data[DATA]); |
を使うと書きました。
要素数が省略できるなら、こちらの方が楽なイメージがありますが、個人的には(要素数あり)にしたいです。
なぜかと言うと、2次元配列が関係しますので、下で説明します。
2次元配列について書きます。
2次元配列の要素数も省略出来るかどうか、次のプログラムで試してみましょう。
#include <stdio.h> #define ROW 2 #define COL 3 void ShowArray(int data[ROW][COL]); int main(void) { int data[ROW][COL] = { {2, 5, 8}, {3, 6, 9}, }; ShowArray(data); return 0; } void ShowArray(int data[ROW][COL]) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%2d", data[i][j]); } printf("\n"); } } |
<実行結果>
2 5 8 3 6 9 続行するには何かキーを押してください・・・
このプログラムの要素数を削除してみます。
<sample program col033-05>
#include <stdio.h> #define ROW 2 #define COL 3 void ShowArray(int data[][]); int main(void) { int data[ROW][COL] = { { 2, 5, 8 }, { 3, 6, 9 }, }; ShowArray(data); return 0; } void ShowArray(int data[][]) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%2d", data[i][j]); } printf("\n"); } } |
コンパイルの時点でエラーが発生しました。
error C2087: 'data': 添字がありません。 error C2664: 'void ShowArray(int [][])': 引数 1 を 'int [2][3]' から 'int [][]' へ変換できません。 note: 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 error C2087: 'data': 添字がありません。
2次元配列では省略は出来なさそうです・・・が、こうすれば出来ます。
<sample program col033-06>
#include <stdio.h> #define ROW 2 #define COL 3 void ShowArray(int data[][COL]); int main(void) { int data[ROW][COL] = { {2, 5, 8}, {3, 6, 9}, }; ShowArray(data); return 0; } void ShowArray(int data[][COL]) { int i; int j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { printf("%2d", data[i][j]); } printf("\n"); } } |
<実行結果>
2 5 8 3 6 9 続行するには何かキーを押してください・・・
最初の要素数は省略可能ですが、2番目の要素数は省略出来ません。
1次元配列も2次元配列も最初の要素数は省略可能です。
しかし、2番目以降の要素数は省略出来ません。
省略することで、要素数が知りたいときに探さなければいけない、という状況は作りたくありません。
ですから、この講座では省略しない方法を採用することにします。
2次元配列も配列の先頭アドレスを渡しています。
実際にアドレスを見てみましょう。
分かりやすくするために、元データの変数名と引数の変数名を変えて作ります。
<sample program col033-07>
#include <stdio.h> #define ROW 2 #define COL 3 void ShowArray(int receive[ROW][COL]); int main(void) { int data[ROW][COL] = { { 2, 5, 8 }, { 3, 6, 9 }, }; printf("data = %p\n", data); ShowArray(data); return 0; } void ShowArray(int receive[ROW][COL]) { printf("receive = %p\n", receive); } |
<実行結果>
data = 00BDF88C receive = 00BDF88C 続行するには何かキーを押してください・・・
※実行結果は毎回変わる可能性があります。
同じアドレスが入っていることが分かります。
では、ポインタ変数で受け取ることは出来るでしょうか。
引数をポインタ変数「pData」に変えてみます。
<sample program col033-08>
#include <stdio.h> #define ROW 2 #define COL 3 void ShowArray(int *pData); int main(void) { int data[ROW][COL] = { { 2, 5, 8 }, { 3, 6, 9 }, }; printf("data = %p\n", data); ShowArray(data); return 0; } void ShowArray(int *pData) { printf("pData = %p\n", pData); } |
コンパイル時にエラーが出ました。
error C2664: 'void ShowArray(int *)': 引数 1 を 'int [2][3]' から 'int *' へ変換できません。
1次元配列の時は出なかったのですが、2次元配列ではエラーになりました。
1次元配列と2次元配列では、仕組みが違うと考えておいてください。
ブラウザの戻るボタンで戻ってください。