[C言語] 関数に配列を渡して値を書き換える方法を解説

C言語では、配列を関数に渡す際に配列の先頭アドレスが渡されます。これにより、関数内で配列の要素を直接書き換えることが可能です。

関数の引数として配列を指定する際には、配列の型とサイズを指定する必要はなく、ポインタとして渡されます。

例えば、void modifyArray(int arr[], int size)のように関数を定義し、関数内でarr[i] = newValueとすることで、元の配列の値を変更できます。

この特性を利用することで、効率的にデータを操作することができます。

この記事でわかること
  • 配列のアドレスを関数に渡す方法とその重要性
  • ポインタを使った配列の値の書き換え方法
  • 多次元配列や動的メモリ割り当ての活用法
  • 配列のソートやフィルタリングの実践的な手法

目次から探す

関数に配列を渡す方法

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

この例では、numbersという配列の先頭アドレスをprintArray関数に渡しています。

関数内で配列の要素を表示しています。

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

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

C言語では配列のサイズ情報が自動的に渡されないため、関数内で配列のサイズを知るためには、要素数を引数として渡す必要があります。

ポインタを使った配列の受け取り方

関数で配列を受け取る際には、ポインタを使って受け取ります。

配列名は配列の先頭アドレスを指しているため、ポインタを使うことで配列の要素にアクセスできます。

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

この例では、doubleArray関数で配列の各要素を2倍にしています。

ポインタを使って配列の要素を直接操作しています。

配列の値を書き換える方法

C言語では、配列の値を関数内で書き換えることができます。

ここでは、ポインタを使った値の書き換えや、関数内での配列操作について詳しく解説します。

ポインタを使った値の書き換え

配列の値を変更する際には、ポインタを使うことで直接配列の要素にアクセスし、値を変更することができます。

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

#include <stdio.h>
// 配列の要素を3倍にする関数
void tripleArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        *(array + i) *= 3; // ポインタを使って値を変更
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のアドレスを渡して要素を3倍にする
    tripleArray(numbers, size);
    
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
3 6 9 12 15

この例では、tripleArray関数でポインタを使って配列の各要素を3倍にしています。

関数内での配列の操作

関数内で配列を操作する際には、配列のアドレスを渡すことで、関数内で直接配列の要素を変更することができます。

これにより、関数外でも変更が反映されます。

#include <stdio.h>
// 配列の要素を負の値にする関数
void negateArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] = -array[i];
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のアドレスを渡して要素を負の値にする
    negateArray(numbers, size);
    
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
-1 -2 -3 -4 -5

この例では、negateArray関数で配列の各要素を負の値にしています。

ループを使った配列の更新

配列の要素を更新する際には、ループを使って効率的に操作することができます。

ループを使うことで、配列の全ての要素に対して同じ操作を簡単に適用できます。

#include <stdio.h>
// 配列の要素をインクリメントする関数
void incrementArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i]++;
    }
}
int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列のアドレスを渡して要素をインクリメントする
    incrementArray(numbers, size);
    
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
2 3 4 5 6

この例では、incrementArray関数で配列の各要素を1ずつ増やしています。

配列の要素を変更する際の注意点

配列の要素を変更する際には、以下の点に注意が必要です。

  • 配列の範囲を超えない: 配列の範囲外にアクセスすると、未定義の動作を引き起こす可能性があります。
  • ポインタの正しい使用: ポインタを使う際には、正しいアドレスを指していることを確認する必要があります。
  • 配列のサイズを確認: 配列のサイズを正しく把握し、ループの範囲を設定することが重要です。

これらの注意点を守ることで、安全に配列の要素を変更することができます。

応用例

配列の操作はC言語プログラミングにおいて非常に重要です。

ここでは、文字列配列の操作、多次元配列の書き換え、動的メモリ割り当て、配列のソートとフィルタリングについて解説します。

文字列配列の操作

文字列は文字の配列として扱われます。

文字列配列を操作することで、文字列の結合や変更が可能です。

#include <stdio.h>
#include <string.h>
// 文字列を大文字に変換する関数
void toUpperCase(char *str) {
    for (int i = 0; str[i] != '\0'; i++) {
        if (str[i] >= 'a' && str[i] <= 'z') {
            str[i] = str[i] - ('a' - 'A');
        }
    }
}
int main() {
    char greeting[] = "hello, world!";
    
    // 文字列を大文字に変換
    toUpperCase(greeting);
    
    // 結果を表示
    printf("%s\n", greeting);
    
    return 0;
}
HELLO, WORLD!

この例では、toUpperCase関数で文字列を大文字に変換しています。

多次元配列の書き換え

多次元配列は、行列のようにデータを格納するのに便利です。

多次元配列の要素を変更することで、データの操作が可能です。

#include <stdio.h>
// 行列の要素を2倍にする関数
void doubleMatrix(int matrix[2][3]) {
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            matrix[i][j] *= 2;
        }
    }
}
int main() {
    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    
    // 行列の要素を2倍にする
    doubleMatrix(matrix);
    
    // 結果を表示
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    
    return 0;
}
2 4 6 
8 10 12

この例では、doubleMatrix関数で多次元配列の各要素を2倍にしています。

配列の動的メモリ割り当て

動的メモリ割り当てを使うことで、実行時に配列のサイズを決定することができます。

malloc関数を使ってメモリを確保し、free関数で解放します。

#include <stdio.h>
#include <stdlib.h>
// 配列の要素を初期化する関数
void initializeArray(int *array, int size) {
    for (int i = 0; i < size; i++) {
        array[i] = i + 1;
    }
}
int main() {
    int size = 5;
    int *numbers = (int *)malloc(size * sizeof(int));
    
    if (numbers == NULL) {
        printf("メモリの割り当てに失敗しました。\n");
        return 1;
    }
    
    // 配列を初期化
    initializeArray(numbers, size);
    
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    // メモリを解放
    free(numbers);
    
    return 0;
}
1 2 3 4 5

この例では、mallocを使って動的にメモリを割り当て、initializeArray関数で配列を初期化しています。

配列のソートとフィルタリング

配列のソートやフィルタリングは、データの整理や特定の条件に基づくデータの抽出に役立ちます。

#include <stdio.h>
#include <stdlib.h>
// 配列を昇順にソートする関数
int compare(const void *a, const void *b) {
    return (*(int *)a - *(int *)b);
}
int main() {
    int numbers[] = {5, 2, 9, 1, 5, 6};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    // 配列をソート
    qsort(numbers, size, sizeof(int), compare);
    
    // 結果を表示
    for (int i = 0; i < size; i++) {
        printf("%d ", numbers[i]);
    }
    printf("\n");
    
    return 0;
}
1 2 5 5 6 9

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

compare関数を使ってソートの基準を指定しています。

よくある質問

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

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

配列のサイズ情報は関数に渡されないため、関数を呼び出す際に配列のサイズを引数として渡す必要があります。

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

配列を関数に渡す際のエラーを防ぐには?

配列を関数に渡す際のエラーを防ぐためには、以下の点に注意することが重要です。

  • 正しいサイズを渡す: 配列のサイズを正確に計算し、関数に渡すようにします。
  • ポインタの使用: 配列の先頭アドレスをポインタとして渡し、関数内で正しく操作します。
  • 範囲外アクセスの防止: 配列の範囲外にアクセスしないように、ループの条件を正しく設定します。

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

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

  • メモリの割り当て: 配列は宣言時に固定サイズのメモリが割り当てられますが、ポインタは動的にメモリを割り当てることができます。
  • サイズ情報: 配列はサイズ情報を持ちますが、ポインタはサイズ情報を持ちません。

ポインタを使う場合は、サイズを別途管理する必要があります。

  • 操作方法: 配列名は配列の先頭アドレスを指しますが、ポインタは任意のメモリアドレスを指すことができます。

まとめ

配列を関数に渡して値を書き換える方法について、基本的な操作から応用例までを解説しました。

配列のアドレスを渡す方法や、ポインタを使った操作、多次元配列や動的メモリ割り当ての活用法を学びました。

これらの知識を活用して、より効率的なプログラムを作成してみてください。

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