[C言語] 関数に配列のポインタを渡して処理する方法を解説

C言語では、配列を関数に渡す際に配列のポインタを使用します。これは、配列の先頭要素のアドレスを関数に渡すことで実現されます。

関数の引数として配列を受け取る場合、引数の型は配列の要素型のポインタとして宣言します。例えば、int型の配列を渡す場合、引数はint *とします。

この方法により、関数内で配列の要素にアクセスしたり、変更を加えることが可能です。配列のサイズ情報は別途渡す必要があるため、通常は配列の長さも引数として渡します。

この記事でわかること
  • 配列とポインタの基本的な概念とその関係
  • 配列のポインタを使った関数の実装方法
  • 多次元配列を関数に渡す際の注意点と方法
  • 配列の要素をソート、検索、集計する応用例
  • 配列のポインタを使う利点とその活用方法

目次から探す

配列とポインタの基礎知識

C言語において、配列とポインタは非常に重要な概念です。

これらを理解することで、メモリ管理や効率的なデータ操作が可能になります。

ここでは、配列とポインタの基本的な特徴を簡単に説明します。

配列の基本

  • 定義: 配列は、同じ型のデータを連続して格納するためのデータ構造です。
  • 宣言方法: 配列は、型名、配列名、要素数を指定して宣言します。
  • 例: int numbers[5]; // 整数型の配列を5つの要素で宣言
  • アクセス方法: 配列の要素には、インデックスを使用してアクセスします。

インデックスは0から始まります。

  • 例: numbers[0] = 10; // 配列の最初の要素に10を代入

ポインタの基本

  • 定義: ポインタは、メモリ上のアドレスを格納するための変数です。
  • 宣言方法: ポインタは、型名の後にアスタリスク(*)を付けて宣言します。
  • 例: int *ptr; // 整数型のポインタを宣言
  • アドレス演算子: 変数のアドレスを取得するには、アドレス演算子(&)を使用します。
  • 例: ptr = &numbers[0]; // 配列の最初の要素のアドレスをポインタに代入
  • 間接演算子: ポインタが指すアドレスの値を取得するには、間接演算子(*)を使用します。
  • 例: int value = *ptr; // ポインタが指すアドレスの値を取得

配列とポインタの関係

  • 配列名は、配列の最初の要素のアドレスを指すポインタとして扱われます。
  • 配列の要素にアクセスする際、ポインタ演算を利用することができます。
  • 例: *(numbers + 1)numbers[1] と同じ意味です。

このように、配列とポインタは密接に関連しており、C言語のプログラミングにおいて重要な役割を果たします。

次のセクションでは、これらの知識を基に、配列のポインタを関数に渡す方法について詳しく解説します。

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

配列のポインタを関数に渡すことで、配列の要素を効率的に操作することができます。

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

関数プロトタイプの定義

関数プロトタイプは、関数の宣言部分であり、関数の名前、戻り値の型、引数の型を指定します。

配列のポインタを引数として受け取る関数プロトタイプは次のように定義します。

void processArray(int *array, int size);
  • int *array: 配列のポインタを受け取る引数
  • int size: 配列のサイズを受け取る引数

配列のポインタを受け取る関数の実装

配列のポインタを受け取る関数を実装する際には、ポインタを使って配列の要素を操作します。

以下は、配列の要素を2倍にする関数の例です。

#include <stdio.h>
// 配列の要素を2倍にする関数
void doubleArrayElements(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] *= 2; // 各要素を2倍にする
    }
}

配列の要素を操作する方法

配列の要素を操作する際には、ポインタ演算を利用することができます。

以下の例では、ポインタを使って配列の要素を操作しています。

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

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

配列のポインタを使った関数を呼び出す際には、配列名を渡すだけで、配列のポインタが渡されます。

以下は、関数を呼び出す例です。

#include <stdio.h>
// 配列の要素を2倍にする関数
void doubleArrayElements(int *array, int size);
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    // 関数を呼び出して配列の要素を2倍にする
    doubleArrayElements(numbers, size);
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
2 4 6 8 10

このプログラムでは、doubleArrayElements関数を呼び出すことで、配列 numbers の各要素が2倍になり、結果が表示されます。

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

多次元配列のポインタを渡す

多次元配列は、行列のようにデータを格納するための構造で、C言語では特に2次元配列がよく使われます。

ここでは、多次元配列の基礎から、ポインタを使った関数への渡し方までを解説します。

多次元配列の基礎

  • 定義: 多次元配列は、配列の中にさらに配列がある構造です。

2次元配列は、行と列で構成されます。

  • 宣言方法: 多次元配列は、型名、配列名、各次元のサイズを指定して宣言します。
  • 例: int matrix[3][4]; // 3行4列の整数型2次元配列を宣言
  • アクセス方法: 多次元配列の要素には、行と列のインデックスを使用してアクセスします。
  • 例: matrix[1][2] = 5; // 2行目3列目の要素に5を代入

多次元配列のポインタの扱い方

多次元配列のポインタを扱う際には、配列の各次元のサイズを考慮する必要があります。

2次元配列の場合、ポインタは行の先頭を指します。

  • ポインタの宣言: 2次元配列のポインタは、行のサイズを指定して宣言します。
  • 例: int (*ptr)[4]; // 4列の2次元配列を指すポインタを宣言
  • ポインタの初期化: 配列の先頭アドレスをポインタに代入します。
  • 例: ptr = matrix; // 配列 matrix の先頭アドレスをポインタに代入

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

多次元配列を関数に渡す際には、関数プロトタイプで各次元のサイズを指定する必要があります。

以下は、2次元配列を関数に渡す例です。

#include <stdio.h>
// 2次元配列の要素を表示する関数
void printMatrix(int rows, int cols, int matrix[rows][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 matrix[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    // 関数を呼び出して2次元配列の要素を表示
    printMatrix(3, 4, matrix);
    return 0;
}
1 2 3 4
5 6 7 8
9 10 11 12

このプログラムでは、printMatrix関数を呼び出すことで、2次元配列 matrix の各要素が表示されます。

関数プロトタイプで行数と列数を指定することで、多次元配列を正しく渡すことができます。

応用例

配列のポインタを使った関数は、さまざまな応用が可能です。

ここでは、配列の要素をソート、検索、集計する関数の例を紹介します。

配列の要素をソートする関数

配列の要素をソートするには、一般的にバブルソートやクイックソートなどのアルゴリズムを使用します。

以下は、バブルソートを用いて配列を昇順にソートする関数の例です。

#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, 2, 9, 1, 5, 6};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    // 配列をソート
    bubbleSort(numbers, size);
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
1 2 5 5 6 9

このプログラムでは、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; // 見つからなかった場合、-1を返す
}
int main() {
    int numbers[] = {5, 2, 9, 1, 5, 6};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    int target = 9;
    // 配列内の値を検索
    int index = linearSearch(numbers, size, target);
    // 結果を表示
    if (index != -1) {
        printf("値 %d はインデックス %d にあります。\n", target, index);
    } else {
        printf("値 %d は配列に存在しません。\n", target);
    }
    return 0;
}
値 9 はインデックス 2 にあります。

このプログラムでは、linearSearch関数を使用して配列 numbers 内の値 9 を検索し、見つかった場合はそのインデックスを表示します。

配列の要素を集計する関数

配列の要素を集計することで、合計や平均を計算することができます。

以下は、配列の要素の合計を計算する関数の例です。

#include <stdio.h>
// 配列の要素の合計を計算する関数
int sumArray(int *array, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += array[i];
    }
    return sum;
}
int main() {
    int numbers[] = {5, 2, 9, 1, 5, 6};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    // 配列の合計を計算
    int total = sumArray(numbers, size);
    // 結果を表示
    printf("配列の合計は %d です。\n", total);
    return 0;
}
配列の合計は 28 です。

このプログラムでは、sumArray関数を使用して配列 numbers の要素の合計を計算し、結果を表示します。

これにより、配列のデータを集計することができます。

よくある質問

配列のサイズを関数内で取得する方法は?

C言語では、配列のサイズを関数内で直接取得することはできません。

配列のサイズは、関数に渡す前に計算し、関数の引数として渡す必要があります。

例えば、int size = sizeof(array) / sizeof(array[0]); のようにしてサイズを計算し、関数に size を渡します。

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

ポインタと配列は似ていますが、いくつかの違いがあります。

  • メモリ管理: 配列は固定サイズでメモリに割り当てられますが、ポインタは動的にメモリを割り当てることができます。
  • 操作: 配列名は配列の先頭アドレスを指すポインタとして扱われますが、ポインタは任意のメモリアドレスを指すことができます。
  • サイズ: 配列のサイズはコンパイル時に決定されますが、ポインタは指す先のサイズを変更できます。

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

配列のポインタを使う理由は、メモリ効率と柔軟性の向上です。

ポインタを使うことで、関数に配列を渡す際にコピーを作成せずに済み、メモリの使用量を削減できます。

また、ポインタを使うことで、配列の一部を操作したり、動的にメモリを管理したりすることが可能になります。

まとめ

配列のポインタを使うことで、C言語におけるデータ操作が効率的に行えます。

配列とポインタの基礎を理解し、関数に配列のポインタを渡す方法や応用例を学ぶことで、プログラムの柔軟性と効率を向上させることができます。

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

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