C言語でポインタを使って2次元配列を関数に渡す方法
ポインタの基礎
まず、ポインタの基礎について理解しておきましょう。ポインタは、変数のアドレスを格納する変数です。アドレスとは、メモリ上の特定の場所を指す番号です。
ポインタを使って変数の値を参照するには、*
演算子を使用します。例えば、int x = 10;
と宣言し、int *ptr = &x;
とすると、ptr
は x
のアドレスを格納します。そして、*ptr
とすると、x
の値である 10
を取得することができます。
2次元配列とポインタ
2次元配列をポインタを使って渡すには、以下の2つの方法があります。
方法1: 各行の先頭要素へのポインタの配列を渡す
この方法では、まず各行の先頭要素へのポインタを格納する配列を準備します。そして、その配列を関数に渡します。
// 2次元配列の宣言
int array[2][5];
// 各行の先頭要素へのポインタの配列
int *pointers[2];
// 各行の先頭要素へのポインタを格納
pointers[0] = array[0];
pointers[1] = array[1];
// 関数への引数としてポインタの配列を渡す
void function(int **pointers) {
// ...
}
int main() {
// ...
function(pointers);
// ...
return 0;
}
方法2: 2次元配列全体を指すポインタを渡す
この方法では、2次元配列全体を指すポインタを関数に渡します。
// 2次元配列の宣言
int array[2][5];
// 2次元配列全体を指すポインタ
int (*ptr)[5] = array;
// 関数への引数として2次元配列全体を指すポインタを渡す
void function(int (*ptr)[5]) {
// ...
}
int main() {
// ...
function(ptr);
// ...
return 0;
}
それぞれの方法のメリットとデメリット
方法1
-
メリット:
- 各行へのポインタを個別に操作できるので、柔軟性が高い
- 配列のサイズを変更する必要がない
-
- コードが冗長になる
- ポインタの管理が複雑になる
方法2
-
- 各行へのポインタを個別に操作できない
- 配列のサイズを変更する必要がある場合、コードを変更する必要がある
#include <stdio.h>
// 2次元配列の宣言
int array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
// 各行の先頭要素へのポインタの配列
int *pointers[2];
// 各行の先頭要素へのポインタを格納
void init_pointers() {
pointers[0] = array[0];
pointers[1] = array[1];
}
// 2次元配列全体を指すポインタ
int (*ptr)[5] = array;
// 各要素を出力する関数
void print_array(int (*ptr)[5], int rows, int columns) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
printf("%d ", ptr[i][j]);
}
printf("\n");
}
}
int main() {
// 各行の先頭要素へのポインタの配列を初期化
init_pointers();
// 各要素を出力
printf("各行の先頭要素へのポインタの配列を使用:\n");
print_array(pointers, 2, 5);
// 2次元配列全体を指すポインタを使用
printf("2次元配列全体を指すポインタを使用:\n");
print_array(ptr, 2, 5);
return 0;
}
print_array()
関数は、各行の先頭要素へのポインタの配列を受け取ります。print_array()
関数は、2次元配列全体を指すポインタを受け取ります。
どちらの方法でも、2次元配列の各要素を出力することができます。
- ポインタを使う場合は、メモリリークが発生しないように注意する必要があります。
2次元配列を関数に渡す他の方法
2次元配列を1次元配列として渡す
2次元配列を1次元配列として渡す方法は、最も単純な方法です。ただし、この方法では、2次元配列の構造が失われてしまうため、注意が必要です。
// 2次元配列を1次元配列として渡す
void function(int *array, int rows, int columns) {
// ...
}
int main() {
// 2次元配列の宣言
int array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
// 2次元配列を1次元配列として関数に渡す
function(array, 2, 5);
return 0;
}
構造体を使う
2次元配列を構造体として渡す方法は、2次元配列の構造を保持することができます。
// 2次元配列を表す構造体
typedef struct {
int rows;
int columns;
int **array;
} Array2D;
// 構造体を関数に渡す
void function(Array2D array) {
// ...
}
int main() {
// 2次元配列の宣言
int array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
// 構造体変数を宣言
Array2D array2d;
array2d.rows = 2;
array2d.columns = 5;
array2d.array = array;
// 構造体を関数に渡す
function(array2d);
return 0;
}
可変長配列を使う
C99以降では、可変長配列を使って2次元配列を関数に渡すことができます。
// 可変長配列を使って2次元配列を関数に渡す
void function(int array[][5], int rows) {
// ...
}
int main() {
// 2次元配列の宣言
int array[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
// 可変長配列を使って関数に渡す
function(array, 2);
return 0;
}
どの方法を使うべきか
どの方法を使うべきかは、状況によって異なります。
- 2次元配列の構造を保持する必要がない場合は、1番目の方法が最も簡単です。
- 2次元配列の構造を保持する必要がある場合は、2番目の方法または3番目の方法を使う必要があります。
- 可変長配列を使用できる場合は、3番目の方法が最も簡潔です。
c pointers multidimensional-array