
C言語入門|配列を渡すと何が起きるか
「えっ、同じように引数で渡してるのに、結果が違うの?」
C言語を学んでいると、誰もが一度はここで立ち止まります。
普通の変数は安全そうなのに、配列を関数に渡した瞬間、
思いがけず中身が書き換わってしまう。
今回はその入口として、
「変数」と「配列」をそれぞれ関数に渡したときに
何が起きているのかを、実際のコードと図を使ってやさしく確認していきましょう。

まずは実験してみよう(サンプルプログラム)
最初に、通常の変数と配列をそれぞれ関数に渡し、
関数の中で値を変更してみます。
プロジェクト名:10-2-1 ソースファイル名: sample10-2-1.c
#include <stdio.h>
void changeValue(int x) // int型の値を受け取る
{
x = 42; // 値を書き換える
}
void changeArray(int x[]) // 配列を受け取る
{
x[0] = 42; // 先頭要素を書き換える
}
int main(void)
{
int score = 10; // 通常の変数
int points[3] = {10, 20, 30}; // 配列
changeValue(score);
changeArray(points);
printf("score=%d, points[0]=%d\n", score, points[0]);
return 0;
}実行結果
score=10, points[0]=42「同じように渡している」のに結果が違う理由
コードを読むと、こんなふうに感じると思います。
- score に 10 を入れて関数に渡した
- points の先頭にも 10 を入れて関数に渡した
- どちらも 42 に書き換えているように見える
それなのに、結果はこうです。
| 対象 | 関数内での変更 | main関数側の結果 |
|---|---|---|
| 通常の変数 score | 変更される | 影響なし |
| 配列 points | 変更される | 影響あり |
ここに 配列と関数の組み合わせが生むトラブルの正体があります。
引数の独立性という大原則
C言語には、基本となる大切な考え方があります。
引数の独立性(原則)
呼び出し先の関数で引数の内容を書き換えても、
呼び出し元の関数に属する変数には影響を与えない。
これは第8章で学んだ
「ローカル変数は関数ごとに独立している」という話と同じです。
通常の変数の場合
関数呼び出し時、次のことが起きています。
| 項目 | 内容 |
|---|---|
| 渡されるもの | 値そのもの |
| 実体 | コピーが作られる |
| 関数内で変更すると | コピーだけが変わる |
| 呼び出し元への影響 | なし |
図で表すと、こんなイメージです。
- main関数の score と
- changeValue関数の x
は まったく別の箱。
だから、x をどれだけ書き換えても、score は無傷です。
なのに、配列だけ独立しないのはなぜ?
ここが今回の核心です。
配列を引数に書いたつもりでも、
C言語では 配列そのものは渡されていません。
配列引数で実際に渡されているもの
| 見た目 | 実際の中身 |
|---|---|
| int x[] | 配列の先頭要素のアドレス |
つまり、関数はこういう情報を受け取っています。
- 配列のコピー
ではなく - 配列が置かれている場所の情報
そのため、関数内で x[0] を書き換えると、
- 同じメモリを見ている main関数側の配列も
- 当然、一緒に変わってしまう
というわけです。
図で見る「変数」と「配列」の決定的な違い
通常の変数を渡した場合
| 関数 | メモリ |
|---|---|
| main | score = 10 |
| changeValue | x = 10(別コピー) |
→ 独立している
配列を渡した場合
| 関数 | メモリ |
|---|---|
| main | points[0] = 10 |
| changeArray | x[0] → 同じ場所 |
→ 同じメモリを共有している
この「共有」が、便利さと危険さを同時に生みます。
これが不具合の温床になる理由
配列を引数に使うと、
- 呼び出したつもりのない場所が書き換わる。
- 関数の中身を知らないと挙動が読めない。
- 大きなプログラムほど影響範囲が見えなくなる。
といった問題が起こりやすくなります。
だから現場では、
- 配列を渡す関数は仕様を厳密に決める。
- 書き換えるのか、読み取り専用なのかを明確にする。
といった約束が、とても重要になるのです。
まとめ:まだ理由は完全にわからなくていい
この段階では、
- なぜアドレスが渡るのか
- なぜC言語はこの仕様なのか
そこまで理解できていなくても大丈夫です。
今はまず、
配列を関数に渡すと、呼び出し元の中身が変わることがある
この事実を、しっかり体感できればOKです。
次回以降の記事の解説で、
ポインタとメモリの視点から、この動きをもう一段深く見ていきます。
