C言語学習ポータル(無料版) 学習コンテンツ 配列 配列を関数に渡す——入口編

🗃️ 配列

配列を関数に渡す——入口編

無料公開版に収録・読む目安 13分

🎯 配列を関数へ渡す書き方を身につけ、値渡しとの違いに気づける

配列も関数に渡せます。書き方はこうです。

#include <stdio.h>

int sum_of(int a[], int n)      // 配列と、その要素数を受け取る
{
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += a[i];
    }
    return sum;
}

int main(void)
{
    int score[5] = {60, 85, 40, 90, 75};
    printf("%d\n", sum_of(score, 5));   // 350
    return 0;
}

渡すときは score と角カッコなしの名前だけを書きます。受け取る側は int a[] と書き、個数は空のままにします。

なぜ要素数も一緒に渡すのか

ここが最大のポイントです。関数の中では、受け取った配列が何個の要素を持つのか分かりません。sizeof(a) / sizeof(a[0]) を関数の中で書いても、正しい要素数にはなりません。だから個数を第2引数で一緒に渡すのが、Cの標準的な作法です。

「配列を渡すときは、個数もセットで渡す」。これは決まり文句として覚えてください。

なお int a[] の代わりに int a[5] と書くこともできますが、コンパイラはこの 5 を確認しません。書いてあっても守られない数字は、かえって誤解のもとです。素直に int a[] と書き、個数は引数で渡しましょう。

書き換えると、呼び出し元も変わる

t07-07で「引数はコピーが渡る」と学びました。ところが配列は様子が違います。

#include <stdio.h>

void double_all(int a[], int n)
{
    for (int i = 0; i < n; i++) {
        a[i] *= 2;              // 関数の中で書き換える
    }
}

int main(void)
{
    int a[3] = {1, 2, 3};
    double_all(a, 3);
    printf("%d %d %d\n", a[0], a[1], a[2]);   // 2 4 6 ← 変わっている!
    return 0;
}

main の配列がしっかり書き換わりました。値渡しの話と矛盾しているように見えますが、そうではありません。配列そのものはコピーされておらず、渡っているのは「配列が置いてある場所」だからです。関数は、その場所へ出向いて中身を書き換えています。

100万要素の配列を毎回コピーしていたら遅くて仕方がない、という現実的な理由もあります。値渡しの原則は生きたまま、渡っている中身が違う——正体は第2部で明かします。

読むだけなら const を付ける

書き換えない配列には const を付けておくと、うっかり書き換えたときにコンパイラが教えてくれます。

int sum_of(const int a[], int n)

戻り値では配列を返せない

関数から配列そのものを返すことはできません。関数の中で作った配列は、return した瞬間にフレームごと片づけられてしまうからです(t07-06の話です)。そのためCでは、「呼び出し元が用意した配列を渡し、関数はそこへ書き込む」という形をよく使います。上の double_all がまさにその形で、標準ライブラリの関数にも同じ設計が並んでいます。

罠・注意

師範渡っておるのは中身ではなく、置き場所じゃ。理由は洞窟で分かる

まとめ: 配列は「名前だけ」を渡し、要素数を必ず添える。関数の中での書き換えは呼び出し元に届きます。

要点まとめ

アプリで演習問題まで解く(無料・登録不要)

この項目に出てくる用語

関数かんすう

一連の処理に名前を付けてひとまとめにしたもののこと。同じ処理を何度も書かずに、名前を呼ぶだけで再利用できる部品にあたる。printfやscanfも、標準ライブラリがあらかじめ用意してくれている関数の一種。

引数ひきすう

関数を呼び出すときに渡す値のこと。関数の中ではその値を使って処理を行う、外から中への入力口としての役割を果たす。渡す引数の順番や型は、関数側の仮引数の並びに合わせる必要がある。

境界外アクセスきょうかいがいあくせす

配列の要素数を超えた添字にアクセスしてしまう重大な事故のこと。コンパイルは通ってしまうため、実行時に予期せぬ動作を引き起こす。他の変数の領域を書き換えてしまい、原因の分かりにくいバグにつながりやすい。

同じトラックのほかの項目

配列とは——箱の行列配列の宣言と要素へのアクセスができ、変数を並べるより配列が優れる理由を説明できる 添字と0始まりの理由添字が0始まりである理由を理解し、範囲を間違えずにループを書ける 配列とループの黄金コンビforループで配列全体を走査でき、要素数を安全に管理できる 境界外アクセスという重大事故境界外アクセスが未定義動作であることを理解し、危険性と防ぎ方を説明できる 配列の初期化いろいろ配列の初期化の書き方を使い分けられ、未初期化の危険を避けられる 多次元配列2次元配列を宣言・初期化し、二重ループで表として扱える 集計・最大値・検索の定石合計・最大値・線形探索の定型パターンを自力で書ける
‹ 多次元配列 集計・最大値・検索の定石 ›

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版(BOOTH)を見る

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版 / BOOTH