[C言語] 2次元配列を関数に引数として渡す方法

C言語で2次元配列を関数に引数として渡すには、配列のサイズを明示的に指定する必要があります。

関数のプロトタイプでは、配列の行数は省略可能ですが、列数は指定しなければなりません。

例えば、void function(int array[][COLS])のように宣言します。

この方法により、関数内で配列の要素にアクセスすることが可能になります。

また、ポインタを使用して配列を渡すこともできますが、配列のサイズ情報を別途渡す必要があります。

この記事でわかること
  • 2次元配列の基礎知識とメモリ上の配置
  • 関数に2次元配列を渡す際のプロトタイプの定義方法
  • ポインタを使った2次元配列の操作方法
  • 動的メモリ確保を用いた2次元配列の柔軟な扱い方

目次から探す

2次元配列の基礎知識

2次元配列とは

2次元配列は、行と列の2つの次元を持つ配列で、表形式のデータを扱うのに適しています。

C言語では、2次元配列は配列の配列として実装され、各要素は同じデータ型を持ちます。

例えば、整数型の2次元配列は以下のように宣言されます。

int matrix[3][4];

この例では、matrixは3行4列の整数型の2次元配列です。

メモリ上の配置

2次元配列はメモリ上に連続して配置されます。

C言語では、2次元配列は行優先で格納されます。

つまり、最初の行のすべての要素がメモリ上に連続して配置され、その後に次の行の要素が続きます。

以下の表は、3行4列の2次元配列のメモリ上の配置を示しています。

スクロールできます
行番号メモリ上の配置
0matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3]
1matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3]
2matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3]

宣言と初期化の方法

2次元配列の宣言と初期化は、以下のように行います。

宣言時に初期化を行うことで、配列の各要素に初期値を設定できます。

int matrix[3][4] = {
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

この例では、matrixは3行4列の2次元配列で、各要素に初期値が設定されています。

初期化リストを使用することで、配列の要素を簡潔に設定できます。

また、初期化リストの一部を省略することも可能で、その場合は省略された要素はデフォルト値(整数型の場合は0)で初期化されます。

関数に2次元配列を渡す基本

2次元配列を関数に渡す際には、配列のサイズやポインタを適切に扱う必要があります。

ここでは、関数プロトタイプの定義方法や配列のサイズ指定、ポインタを使った渡し方について解説します。

関数プロトタイプの定義

2次元配列を関数に渡すためには、関数プロトタイプを正しく定義する必要があります。

関数プロトタイプでは、配列の行数を指定し、列数を明示する必要があります。

以下は、2次元配列を引数に取る関数のプロトタイプの例です。

void processMatrix(int matrix[][4], int rows);

この例では、processMatrixという関数が2次元配列matrixと行数rowsを引数として受け取ります。

列数4は固定されているため、プロトタイプで明示されています。

配列のサイズ指定

関数に2次元配列を渡す際には、少なくとも列数を指定する必要があります。

行数は関数内で別途引数として渡すことが一般的です。

以下のコードは、2次元配列を関数に渡す際のサイズ指定の例です。

void printMatrix(int matrix[][4], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

この関数printMatrixは、行数rowsを引数として受け取り、配列の各要素を出力します。

ポインタを使った渡し方

2次元配列をポインタとして渡す方法もあります。

この方法では、配列の先頭アドレスをポインタとして渡し、関数内で配列を操作します。

以下は、ポインタを使った2次元配列の渡し方の例です。

void modifyMatrix(int *matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            *(matrix + i * cols + j) += 1; // 各要素に1を加算
        }
    }
}

この例では、modifyMatrix関数がポインタmatrixを受け取り、行数rowsと列数colsを使って配列の各要素にアクセスしています。

ポインタを使うことで、配列のサイズを柔軟に扱うことができます。

以上の方法を理解することで、2次元配列を関数に渡す際の基本的なテクニックを習得できます。

具体的なコード例

ここでは、2次元配列を関数に渡す具体的なコード例を紹介します。

これらの例を通じて、2次元配列の操作方法を理解しましょう。

2次元配列を引数に取る関数の例

以下のコードは、2次元配列を引数に取る関数の例です。

この関数は、配列の各要素を出力します。

#include <stdio.h>
// 2次元配列を引数に取る関数
void printMatrix(int matrix[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}
int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    printMatrix(matrix, 2);
    return 0;
}
1 2 3 
4 5 6 

このコードでは、printMatrix関数が2次元配列matrixを受け取り、各要素を出力しています。

配列の要素を操作する関数の例

次に、2次元配列の要素を操作する関数の例を示します。

この関数は、配列の各要素に1を加算します。

#include <stdio.h>
// 配列の要素を操作する関数
void incrementMatrix(int matrix[][3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            matrix[i][j] += 1;
        }
    }
}
int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    incrementMatrix(matrix, 2);
    printMatrix(matrix, 2); // 先ほどのprintMatrix関数を使用
    return 0;
}
2 3 4 
5 6 7 

このコードでは、incrementMatrix関数が配列の各要素に1を加算し、printMatrix関数で結果を出力しています。

配列のサイズを動的に扱う例

最後に、配列のサイズを動的に扱う例を示します。

この例では、ポインタを使って2次元配列を操作します。

#include <stdio.h>
#include <stdlib.h>
// 動的に配列を操作する関数
void dynamicMatrix(int *matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            *(matrix + i * cols + j) = i * cols + j;
        }
    }
}
int main() {
    int rows = 3, cols = 4;
    int *matrix = (int *)malloc(rows * cols * sizeof(int));
    dynamicMatrix(matrix, rows, cols);
    // 結果を出力
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", *(matrix + i * cols + j));
        }
        printf("\n");
    }
    free(matrix);
    return 0;
}
0 1 2 3 
4 5 6 7 
8 9 10 11 

このコードでは、dynamicMatrix関数が動的に確保したメモリを使って2次元配列を操作し、各要素に値を設定しています。

動的メモリを使用することで、配列のサイズを柔軟に扱うことができます。

ポインタと2次元配列

ポインタはC言語において非常に強力な機能であり、2次元配列を操作する際にも重要な役割を果たします。

ここでは、ポインタと配列の関係、ポインタを使った2次元配列の操作、そしてポインタ配列を使った関数への渡し方について解説します。

ポインタと配列の関係

配列とポインタは密接な関係にあります。

配列の名前は、その配列の先頭要素のアドレスを指すポインタとして扱われます。

例えば、int matrix[3][4];という2次元配列がある場合、matrixmatrix[0]の先頭アドレスを指すポインタとして扱われます。

以下の表は、配列とポインタの関係を示しています。

スクロールできます
配列名ポインタとしての意味
matrix&matrix[0](最初の行の先頭アドレス)
matrix[i]&matrix[i][0](i番目の行の先頭アドレス)

ポインタを使った2次元配列の操作

ポインタを使って2次元配列を操作することができます。

ポインタを使うことで、配列の要素にアクセスしたり、操作したりすることが可能です。

以下のコードは、ポインタを使って2次元配列の要素を操作する例です。

#include <stdio.h>
// ポインタを使った2次元配列の操作
void modifyMatrix(int *matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            *(matrix + i * cols + j) += 10; // 各要素に10を加算
        }
    }
}
int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    modifyMatrix((int *)matrix, 2, 3);
    // 結果を出力
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    return 0;
}
11 12 13 
14 15 16 

このコードでは、modifyMatrix関数がポインタを使って2次元配列の各要素に10を加算しています。

ポインタ配列を使った関数への渡し方

ポインタ配列を使って2次元配列を関数に渡す方法もあります。

この方法では、各行を指すポインタの配列を作成し、それを関数に渡します。

以下のコードは、ポインタ配列を使った関数への渡し方の例です。

#include <stdio.h>
// ポインタ配列を使った関数
void printMatrix(int *matrix[], int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}
int main() {
    int row1[] = {1, 2, 3};
    int row2[] = {4, 5, 6};
    int *matrix[] = {row1, row2};
    printMatrix(matrix, 2, 3);
    return 0;
}
1 2 3 
4 5 6 

このコードでは、各行を指すポインタの配列matrixを作成し、printMatrix関数に渡しています。

ポインタ配列を使うことで、関数に渡す際の柔軟性が向上します。

応用例

2次元配列を関数に渡す方法は、さまざまな応用が可能です。

ここでは、文字列の2次元配列を関数に渡す方法、動的メモリ確保を用いた2次元配列の渡し方、そして多次元配列を関数に渡す方法について解説します。

文字列の2次元配列を関数に渡す

文字列の2次元配列は、文字列の配列として扱われます。

各文字列は文字の配列であり、2次元配列として関数に渡すことができます。

以下のコードは、文字列の2次元配列を関数に渡す例です。

#include <stdio.h>
// 文字列の2次元配列を関数に渡す
void printStrings(char strings[][20], int count) {
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}
int main() {
    char strings[3][20] = {"Hello", "World", "C Language"};
    printStrings(strings, 3);
    return 0;
}
Hello
World
C Language

このコードでは、printStrings関数が文字列の2次元配列を受け取り、各文字列を出力しています。

動的メモリ確保を用いた2次元配列の渡し方

動的メモリ確保を用いることで、実行時に配列のサイズを決定することができます。

以下のコードは、動的メモリ確保を用いた2次元配列の渡し方の例です。

#include <stdio.h>
#include <stdlib.h>
// 動的メモリ確保を用いた2次元配列の渡し方
void fillMatrix(int **matrix, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            matrix[i][j] = i * cols + j;
        }
    }
}
int main() {
    int rows = 3, cols = 4;
    int **matrix = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; i++) {
        matrix[i] = (int *)malloc(cols * sizeof(int));
    }
    fillMatrix(matrix, rows, cols);
    // 結果を出力
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    // メモリの解放
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);
    return 0;
}
0 1 2 3 
4 5 6 7 
8 9 10 11 

このコードでは、fillMatrix関数が動的に確保したメモリを使って2次元配列を操作し、各要素に値を設定しています。

多次元配列を関数に渡す方法

多次元配列を関数に渡す場合も、2次元配列と同様に扱うことができます。

ただし、すべての次元のサイズを指定する必要があります。

以下のコードは、多次元配列を関数に渡す方法の例です。

#include <stdio.h>
// 多次元配列を関数に渡す
void print3DArray(int array[][3][2], int depth) {
    for (int i = 0; i < depth; i++) {
        printf("Layer %d:\n", i);
        for (int j = 0; j < 3; j++) {
            for (int k = 0; k < 2; k++) {
                printf("%d ", array[i][j][k]);
            }
            printf("\n");
        }
    }
}
int main() {
    int array[2][3][2] = {
        {{1, 2}, {3, 4}, {5, 6}},
        {{7, 8}, {9, 10}, {11, 12}}
    };
    print3DArray(array, 2);
    return 0;
}
Layer 0:
1 2 
3 4 
5 6 
Layer 1:
7 8 
9 10 
11 12 

このコードでは、print3DArray関数が3次元配列を受け取り、各要素を出力しています。

多次元配列を扱う際には、すべての次元のサイズを指定することが重要です。

よくある質問

2次元配列のサイズを関数内で変更できますか?

2次元配列のサイズを関数内で直接変更することはできません。

C言語では、配列のサイズはコンパイル時に決定されるため、関数内でサイズを変更することはできません。

ただし、動的メモリ確保を使用することで、実行時に配列のサイズを変更することが可能です。

例えば、malloc関数を使って新しいサイズのメモリを確保し、必要に応じてデータをコピーする方法があります。

関数に渡す際に配列のサイズを指定しないとどうなりますか?

関数に2次元配列を渡す際に、少なくとも列数を指定しないと、コンパイルエラーが発生します。

C言語では、配列のサイズ情報が必要であり、特に多次元配列の場合、列数を指定しないとメモリ上の正しい位置にアクセスできなくなります。

したがって、関数プロトタイプで列数を明示することが重要です。

ポインタを使う場合と使わない場合の違いは何ですか?

ポインタを使う場合と使わない場合の主な違いは、柔軟性とメモリ管理です。

ポインタを使うことで、配列のサイズを動的に変更したり、関数間で配列を効率的に渡したりすることができます。

ポインタを使わない場合は、配列のサイズが固定され、コンパイル時に決定されます。

ポインタを使うことで、動的メモリ確保を利用した柔軟なプログラム設計が可能になりますが、メモリ管理を適切に行う必要があります。

まとめ

2次元配列を関数に渡す方法について、基本的な概念から応用例までを詳しく解説しました。

2次元配列の操作には、配列のサイズ指定やポインタの活用が重要であることが理解できたでしょう。

この記事を参考に、実際のプログラムで2次元配列を効果的に活用してみてください。

  • URLをコピーしました!
目次から探す