C言語

【C言語】第4章第6回:ポインタと関数:引数としての利用

ポインタを関数の引数として使用することで、関数内での値の変更を呼び出し元に反映させることができます。この章では、ポインタを引数として活用する方法を具体例を交えて解説します。

1. ポインタを関数の引数として使うとは?

ポインタを関数に渡すことで、関数内で直接変数の値を操作することができます。

1.1 値渡しとアドレス渡しの違い

  • 値渡し:変数の値をコピーして渡すため、元の値は変更されません。
  • アドレス渡し:変数のアドレスを渡すことで、関数内で直接操作できます。

例:値渡しとアドレス渡しの比較

#include <stdio.h>

// 値渡し
void valuePass(int num) {
    num = 20; // 変更は呼び出し元に影響しない
}

// アドレス渡し
void addressPass(int *num) {
    *num = 20; // 変更は呼び出し元に反映される
}

int main() {
    int number = 10;

    printf("Before valuePass: %d\n", number);
    valuePass(number);
    printf("After valuePass: %d\n", number);

    printf("Before addressPass: %d\n", number);
    addressPass(&number); // アドレスを渡す
    printf("After addressPass: %d\n", number);

    return 0;
}

解説:

  • valuePassでは、変数の値がコピーされるため、元の変数は変更されません。
  • addressPassでは、ポインタを使ってアドレスを渡すため、元の変数が変更されます。

2. ポインタを引数として使う利点

  • 複数の値を返す:関数で複数の値を返すことができます。
  • 効率性:大きなデータ構造をコピーせずに操作できます。

2.1 複数の値を返す関数

例:最大値と最小値を同時に返す

#include <stdio.h>

void findMinMax(int arr[], int size, int *min, int *max) {
    *min = *max = arr[0];

    for (int i = 1; i < size; i++) {
        if (arr[i] < *min) {
            *min = arr[i];
        }
        if (arr[i] > *max) {
            *max = arr[i];
        }
    }
}

int main() {
    int numbers[] = {3, 7, 1, 9, 5};
    int min, max;

    findMinMax(numbers, 5, &min, &max);

    printf("Minimum: %d, Maximum: %d\n", min, max);

    return 0;
}

解説:

  • findMinMaxは、配列内の最大値と最小値を見つけ、それぞれをポインタminmaxで返します。
  • 関数から複数の値を返す必要がある場合に便利です。

3. ポインタを使った動的メモリ操作

ポインタを使用して、動的にメモリを割り当てる方法を学びます。

3.1 動的配列の作成

例:ユーザー定義サイズの配列

#include <stdio.h>
#include <stdlib.h>

void createArray(int **arr, int size) {
    *arr = (int *)malloc(size * sizeof(int));

    for (int i = 0; i < size; i++) {
        (*arr)[i] = i + 1;
    }
}

int main() {
    int *array = NULL;
    int size = 5;

    createArray(&array, size);

    printf("Array: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]);
    }
    printf("\n");

    free(array);
    return 0;
}

解説:

  • int **arrはポインタへのポインタで、関数内でポインタを動的に初期化できます。
  • mallocを使用してメモリを割り当て、関数内で値を設定します。

4. 練習問題

以下の課題に挑戦して、ポインタを引数に使うスキルを磨きましょう。

  1. ポインタを使って2つの数値の平均を計算し、呼び出し元で結果を受け取るプログラムを作成してください。
  2. ポインタを使って、指定された文字列の長さを計算する関数を作成してください。
  3. ポインタを使って、配列を逆順に並び替えるプログラムを作成してください。

5. 練習問題の解答と解説

問1の解答

#include <stdio.h>

void calculateAverage(int a, int b, float *result) {
    *result = (a + b) / 2.0;
}

int main() {
    int x = 10, y = 20;
    float average;

    calculateAverage(x, y, &average);

    printf("Average: %.2f\n", average);

    return 0;
}

6. まとめ

ポインタを関数の引数として使用することで、効率的なデータ操作や複数の値の返却が可能になります。これを応用して、より高度なプログラムを構築してみましょう。