[C言語] 関数に配列のポインタを渡す方法

C言語では、関数に配列を渡す際に配列のポインタを使用します。配列の名前自体がその先頭要素のポインタを示すため、関数の引数として配列名を渡すことで、配列全体を渡すことができます。

関数のプロトタイプでは、引数としてint array[]int *arrayと記述することが一般的です。

この方法により、関数内で配列の要素を直接操作することが可能となり、メモリ効率の良いプログラムを作成できます。

この記事でわかること
  • 配列を関数に渡す基本的な方法
  • 配列のポインタを使った関数の実装方法
  • 文字列配列や多次元配列を関数に渡す応用例
  • 配列のポインタを使ったソートや検索関数の実装
  • 配列のポインタと配列の違い、およびその利点

目次から探す

関数に配列を渡す方法

配列を関数に渡す基本

C言語では、配列を関数に渡す際に、配列そのものではなく、配列の先頭要素のポインタを渡します。

これにより、関数内で配列の要素を操作することが可能になります。

以下に基本的な例を示します。

#include <stdio.h>
// 配列を受け取る関数
void printArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列を関数に渡す
    printArray(numbers, size);
    
    return 0;
}
1 2 3 4 5

この例では、printArray関数に配列numbersの先頭要素のポインタと配列のサイズを渡しています。

関数内で配列の要素を順に出力しています。

配列の要素数を渡す必要性

配列を関数に渡す際、配列の要素数を一緒に渡すことが重要です。

C言語では、配列のサイズ情報はポインタには含まれていないため、関数内で配列のサイズを知る手段がありません。

したがって、配列の要素数を引数として渡すことで、関数内で正しく配列を操作できます。

配列のポインタを渡す方法

配列のポインタを渡す方法は、配列の先頭要素のアドレスを渡すことです。

これは、配列名をそのまま渡すことで実現できます。

配列名は配列の先頭要素のポインタとして扱われます。

#include <stdio.h>
// 配列のポインタを受け取る関数
void modifyArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] *= 2; // 各要素を2倍にする
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のポインタを関数に渡す
    modifyArray(numbers, size);
    
    // 変更後の配列を出力
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
2 4 6 8 10

この例では、modifyArray関数に配列numbersのポインタを渡し、各要素を2倍にしています。

関数内での変更は、元の配列に反映されます。

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

ポインタを使って配列を操作することで、関数内で配列の要素を直接変更することができます。

ポインタを使うことで、配列の要素を効率的に操作でき、メモリの使用量を抑えることができます。

以下に、ポインタを使った配列の操作の例を示します。

#include <stdio.h>
// ポインタを使って配列を操作する関数
void reverseArray(int *array, int size) {
    int *start = array;
    int *end = array + size - 1;
    while (start < end) {
        int temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列を逆順にする
    reverseArray(numbers, size);
    
    // 逆順後の配列を出力
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
5 4 3 2 1

この例では、reverseArray関数を使って配列を逆順にしています。

ポインタを使って配列の先頭と末尾から要素を交換することで、効率的に操作を行っています。

配列のポインタを使った関数の実装

配列のポインタを受け取る関数の宣言

配列のポインタを受け取る関数を宣言する際には、関数の引数としてポインタを指定します。

配列の要素の型に応じたポインタ型を使用し、必要に応じて配列のサイズを示す引数も追加します。

以下に基本的な宣言の例を示します。

// 配列のポインタを受け取る関数の宣言
void processArray(int *array, int size);

この宣言では、int型の配列のポインタを受け取り、配列のサイズを示すint型の引数を持つ関数processArrayを宣言しています。

配列のポインタを使った関数の定義

関数の定義では、宣言で指定した引数を用いて、配列のポインタを操作します。

関数内で配列の要素を操作することで、配列の内容を変更したり、特定の処理を行ったりできます。

#include <stdio.h>
// 配列のポインタを使った関数の定義
void processArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] += 10; // 各要素に10を加える
    }
}

この定義では、processArray関数が配列の各要素に10を加える処理を行っています。

関数内での配列操作

関数内で配列を操作する際には、ポインタを使って配列の要素にアクセスします。

ポインタを使うことで、配列の要素を直接変更することができ、効率的な操作が可能です。

#include <stdio.h>
// 配列のポインタを使った関数の定義
void processArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] *= 2; // 各要素を2倍にする
    }
}

この例では、processArray関数が配列の各要素を2倍にする操作を行っています。

配列のポインタを使った関数の呼び出し

配列のポインタを使った関数を呼び出す際には、配列名をそのまま渡すことで、配列の先頭要素のポインタを渡すことができます。

関数内での操作は、元の配列に反映されます。

#include <stdio.h>
// 配列のポインタを使った関数の定義
void processArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] += 5; // 各要素に5を加える
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のポインタを使った関数の呼び出し
    processArray(numbers, size);
    
    // 変更後の配列を出力
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
6 7 8 9 10

この例では、processArray関数を呼び出し、配列numbersの各要素に5を加えています。

関数内での操作が元の配列に反映され、変更後の配列が出力されています。

応用例

文字列配列を関数に渡す

文字列配列を関数に渡す場合、各文字列は文字の配列であり、文字列配列は文字配列の配列として扱われます。

関数に渡す際には、文字列のポインタを渡します。

#include <stdio.h>
// 文字列配列を受け取る関数
void printStrings(char *strings[], int count) {
    for (int i = 0; i < count; i++) {
        printf("%s\n", strings[i]);
    }
}
int main() {
    char *fruits[] = {"Apple", "Banana", "Cherry"};
    int count = sizeof(fruits) / sizeof(fruits[0]);
    
    // 文字列配列を関数に渡す
    printStrings(fruits, count);
    
    return 0;
}
Apple
Banana
Cherry

この例では、printStrings関数に文字列配列fruitsを渡し、各文字列を出力しています。

多次元配列を関数に渡す

多次元配列を関数に渡す場合、配列の次元数に応じたポインタを使用します。

特に、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}};
    
    // 2次元配列を関数に渡す
    printMatrix(matrix, 2);
    
    return 0;
}
1 2 3
4 5 6

この例では、printMatrix関数に2次元配列matrixを渡し、行列を出力しています。

動的配列を関数に渡す

動的配列を関数に渡す場合、通常の配列と同様にポインタを渡します。

動的配列はmalloccallocを使ってメモリを確保します。

#include <stdio.h>
#include <stdlib.h>
// 動的配列を受け取る関数
void initializeArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] = i + 1; // 1から始まる連続した整数で初期化
    }
}
int main() {
    int size = 5;
    int *dynamicArray = (int *)malloc(size * sizeof(int));
    
    if (dynamicArray == NULL) {
        printf("メモリの確保に失敗しました。\n");
        return 1;
    }
    
    // 動的配列を関数に渡す
    initializeArray(dynamicArray, size);
    
    // 初期化後の配列を出力
    for (int i = 0; i < size; i++) {
        printf("%d ", dynamicArray[i]);
    }
    printf("\n");
    
    free(dynamicArray);
    return 0;
}
1 2 3 4 5

この例では、initializeArray関数に動的配列dynamicArrayを渡し、配列を初期化しています。

配列のポインタを使ったソート関数

配列のポインタを使ってソート関数を実装することで、配列の要素を並べ替えることができます。

以下にバブルソートを用いた例を示します。

#include <stdio.h>
// 配列のポインタを使ったソート関数
void bubbleSort(int *array, int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (array[j] > array[j + 1]) {
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
    }
}
int main() {
    int numbers[] = {5, 3, 8, 6, 2};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のポインタを使ったソート関数の呼び出し
    bubbleSort(numbers, size);
    
    // ソート後の配列を出力
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
2 3 5 6 8

この例では、bubbleSort関数を使って配列numbersを昇順にソートしています。

配列のポインタを使った検索関数

配列のポインタを使って検索関数を実装することで、特定の要素を配列内から探すことができます。

以下に線形探索を用いた例を示します。

#include <stdio.h>
// 配列のポインタを使った検索関数
int linearSearch(int *array, int size, int target) {
    for (int i = 0; i < size; i++) {
        if (array[i] == target) {
            return i; // 見つかった場合のインデックスを返す
        }
    }
    return -1; // 見つからなかった場合
}
int main() {
    int numbers[] = {5, 3, 8, 6, 2};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int target = 6;
    
    // 配列のポインタを使った検索関数の呼び出し
    int index = linearSearch(numbers, size, target);
    
    if (index != -1) {
        printf("要素%dはインデックス%dにあります。\n", target, index);
    } else {
        printf("要素%dは配列に存在しません。\n", target);
    }
    
    return 0;
}
要素6はインデックス3にあります。

この例では、linearSearch関数を使って配列numbersから要素6を探し、そのインデックスを出力しています。

見つからない場合は-1を返します。

よくある質問

配列のポインタと配列の違いは何ですか?

配列と配列のポインタは似ていますが、異なる概念です。

配列はメモリ上に連続して配置された要素の集合であり、配列名はその先頭要素のアドレスを指します。

一方、配列のポインタは、配列の先頭要素のアドレスを格納する変数です。

例として、int arr[5]は配列であり、int *ptr = arrは配列のポインタです。

配列名はポインタとして扱われますが、配列そのものではありません。

なぜ配列のポインタを使うのですか?

配列のポインタを使う理由は、関数に配列を渡す際に効率的にメモリを使用できるからです。

配列を関数に渡すとき、配列全体をコピーするのではなく、先頭要素のアドレスを渡すことで、メモリの使用量を抑え、処理速度を向上させることができます。

また、ポインタを使うことで、関数内で配列の要素を直接操作することが可能になります。

配列のサイズを関数に渡す方法は?

配列のサイズを関数に渡す方法は、配列の要素数を示す引数を追加することです。

C言語では、配列のサイズ情報はポインタには含まれていないため、関数内で配列のサイズを知るためには、サイズを別途引数として渡す必要があります。

例として、void processArray(int *array, int size)のように、サイズを引数として渡すことで、関数内で配列のサイズを利用できます。

まとめ

配列のポインタを使って関数に配列を渡す方法は、C言語プログラミングにおいて重要な技術です。

この記事では、配列のポインタを使った関数の実装方法や応用例について詳しく解説しました。

これにより、効率的なメモリ管理と配列操作が可能になります。

この記事を参考に、実際のプログラムで配列のポインタを活用してみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

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