
C言語基礎|配列のコピー
配列を扱っていると、わりと早い段階でこういう場面に出会います。
- 元データは残したまま、加工した配列を作りたい。
- 並びを逆にした配列を別に持ちたい。
- 条件に合う要素だけ抽出して、新しい配列に詰めたい。
つまり 配列をコピーしたいんですね。
ところがC言語では、ここでひっかけポイントがあります。
配列は代入演算子で丸ごとコピーできません。
だから、基本は「要素を1個ずつコピーする」スタイルになります。

まず重要:配列は b = a; ができない
普通の変数なら b = a; でコピーできますが、配列はダメです。
| 対象 | 代入できる? | 例 |
|---|---|---|
| int 変数 | できる | x = y; |
| 配列 | できない | b = a; はエラー |
なので配列コピーは、こういう形が基本になります。
for (i = 0; i < n; i++)
b[i] = a[i];サンプルプログラム
元の a と b の例を、もう少し実務寄りにしてみます。
ここでは「5日分の作業時間(分)」を入力して、バックアップ配列にコピーして表示します。
表示メッセージも別の日本語に置き換えています。
プロジェクト名:chap5-8-1 ソースファイル名:chap5-8-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 配列の全要素を別の配列にコピー(バックアップ)
#include <stdio.h>
#define N 5
int main(void)
{
int work[N]; // コピー元
int backup[N]; // コピー先
printf("%d日分の作業時間(分)を入力してください。\n", N);
for (int i = 0; i < N; i++) {
printf("%d日目:", i + 1);
scanf("%d", &work[i]);
}
for (int i = 0; i < N; i++)
backup[i] = work[i]; // 要素ごとにコピー
puts("\n元データとバックアップを表示します。");
puts(" day work backup");
for (int i = 0; i < N; i++)
printf("%4d%6d%8d\n", i + 1, work[i], backup[i]);
return 0;
}図で理解:配列コピーは「2つの配列を同時に走査」
コピー処理は「同じ添字の要素を順番に代入していく」だけです。

この図が示しているのは「値が同じになる」だけじゃなく、
配列そのものは別物(別の領域)ということです。
だからコピー後に work[0] を変えても、backup[0] は勝手に変わりません。
条件を満たす要素だけコピー(抽出コピー)
全要素コピーを応用すると、よく使うテクとして「フィルタ(抽出)」ができます。
このときの主役が count 変数です。
- コピー先の「次に入れる位置」を管理する
- 条件に合ったときだけ b[count] に入れて、直後に count を増やす
サンプル
「温度データのうち、0以上(正常値)だけログ配列に詰める」みたいな雰囲気の例にします。
プロジェクト名:chap5-8-2 ソースファイル名:chap5-8-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 配列の要素のうち0以上の要素を別の配列にコピー
#include <stdio.h>
#define N 5
int main(void)
{
int temp[N]; // コピー元
int normal[N]; // コピー先
printf("%d個の温度を入力してください(負の値も入力可)。\n", N);
for (int i = 0; i < N; i++) {
printf("temp[%d]:", i);
scanf("%d", &temp[i]);
}
int count = 0;
for (int i = 0; i < N; i++) {
if (temp[i] >= 0)
normal[count++] = temp[i];
}
puts("\n0以上の値だけ取り出しました。");
for (int i = 0; i < count; i++)
printf("normal[%d] = %d\n", i, normal[i]);
return 0;
}count++ の意味を表で整理(ここ超重要)
normal[count++] = temp[i]; は、初心者がつまずきやすいところなので丁寧にいきます。
| 書き方 | 起きること | イメージ |
|---|---|---|
| normal[count] = temp[i]; count++; | 代入してから count を1増やす | 安全で分かりやすい |
| normal[count++] = temp[i]; | 上と同じ意味(後置インクリメント) | 1行で書ける |
後置インクリメント count++ は「式の評価が終わった後に増える」ので、
代入先としては「増える前の count」が使われます。
例:count が 0 のときに代入すると…
- normal[0] に代入
- その後 count が 1 になる
どの命令・演算子が何をしているか(書式つき)
for 文(配列走査)
書式
for (初期化; 条件式; 更新) {
処理
}何をする?
添字を増やしながら、配列要素を先頭から順番に処理します。コピー処理の基本形です。
if 文(条件付きコピー)
書式
if (条件) 文;または
if (条件) {
文;
}何をする?
条件が真のときだけコピーします。抽出コピーで大活躍します。
代入演算子 =
書式
左辺 = 右辺;何をする?
右辺の値を左辺へ入れます。
配列全体には使えないけど、要素(b[i])にはもちろん使えます。
後置インクリメント ++
書式
count++何をする?
式の評価が終わった後に 1 増やします。
抽出コピーでは「入れたら次へ」が自然に書けます。
printf / scanf / puts
- scanf(書式, 格納先アドレス); は入力
- printf(書式, 値...); は表示
- puts(文字列); は1行表示(改行つき)
“配列コピー”でありがちなミス(先に潰す)
| ミス | 何が起きる? | 対策 |
|---|---|---|
| b = a; と書く | コンパイルエラー | ループで要素コピー |
| count を増やし忘れる | 同じ場所に上書きされ続ける | normal[count++] を使う |
| count の上限を意識しない | 配列範囲外アクセス | コピー先のサイズを確保、条件を厳密に |
演習問題
演習5-9
配列 a の要素の並びを逆順にしたものを b にコピーするプログラムを作成せよ。
解答例
プロジェクト名:chap5-8-3 ソースファイル名:chap5-8-3.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
#define N 5
int main(void)
{
int work[N];
int rev[N];
printf("%d個の整数を入力してください。\n", N);
for (int i = 0; i < N; i++) {
printf("work[%d]:", i);
scanf("%d", &work[i]);
}
for (int i = 0; i < N; i++)
rev[i] = work[N - 1 - i]; // 逆順コピー
puts("\n逆順にコピーしました。");
puts(" i work rev");
for (int i = 0; i < N; i++)
printf("%2d%6d%6d\n", i, work[i], rev[i]);
return 0;
}