
C言語入門|メモリ比較と初期化の基本関数
ここまでで、
「配列は = で比較してはいけない」
「配列は = で代入してはいけない」
という、C言語らしい厳しいルールを学んできました。
正直、不便ですよね。
でも安心してください。
C言語は 禁止するだけの言語 ではありません。
その代わりに、正しいやり方をちゃんと用意しています。
今回はその中から、
- メモリの中身を比べる。
- メモリを一気に初期化する。
という、実務で非常によく使われる
2つの基本関数 を紹介します。

なぜ比較や初期化に専用関数が必要なのか
まず、大前提を整理しておきましょう。
== 演算子で比較すると何が起きる?
int a[3];
int b[3];
if (a == b) {
/* … */
}この条件式は、
- a と b の 中身を比べている
のではなく - a と b の 先頭アドレスが同じか
を判定しています。
つまり、
同一の存在かどうか(等値判定)
を調べているだけです。
しかし実際にやりたいのは、多くの場合、
中身が同じかどうか(等価判定)
ですよね。
そこで登場するのが memcmp です。
memcmp ― メモリ領域をまるごと比較する
memcmp は、
指定したバイト数分のメモリ内容を、そっくりそのまま比較する
ための関数です。
配列だけでなく、
「メモリ領域そのもの」を比較する汎用関数です。
memcmp の書式
int memcmp(const void* addr1, const void* addr2, size_t len);引数の意味
| 引数 | 内容 |
|---|---|
| addr1 | 比較元の先頭アドレス |
| addr2 | 比較先の先頭アドレス |
| len | 比較するバイト数 |
戻り値
| 戻り値 | 意味 |
|---|---|
| 0 | 2つのメモリ領域の内容が同じ |
| 0以外 | どこかに違いがある |
配列を memcmp で比較してみよう
次の例では、
中身が同じ int 型配列を比較します。
サンプルプログラム
プロジェクト名:10-8-1 ソースファイル名: sample10-8-1.c
#include <stdio.h>
#include <string.h>
int main(void)
{
int x[3] = {5, 10, 15};
int y[3] = {5, 10, 15};
int r = memcmp(x, y, sizeof(x));
if (r == 0) {
printf("memcmpの結果:配列の中身は同じです\n");
}
if (x == y) {
printf("== の結果:同じ配列です\n");
}
return 0;
}実行結果
memcmpの結果:配列の中身は同じですなぜ == では比較できないのか
x == y が意味するのは、
- x の先頭アドレス
- y の先頭アドレス
が 完全に同じかどうか です。
今回の例では、
- x と y は別々の場所に確保された
- 別の配列
なので、== では常に偽になります。
判定の違いまとめ
| 判定の種類 | 内容 | 手段 |
|---|---|---|
| 等値判定 | 同一の存在か | == 演算子 |
| 等価判定 | 中身が同じか | memcmp |
memcmp を使うときの注意点
構造体の比較には要注意
構造体には、
- パディング(使われない隙間)
が含まれることがあります。
そのため、
- 見た目は同じ
- メンバの値も同じ
でも、
パディング部分が異なっていると
memcmp は「違う」と判定してしまいます。
→ 構造体の比較に memcmp を使うのは原則NG
と覚えておきましょう。
memset ― メモリ領域をまるごと初期化する
次に紹介するのは、初期化専用の関数です。
memset は、
指定したメモリ領域を
同じ1バイトの値で埋め尽くす
ための関数です。
もっともよく使われるのは、0での初期化です。
memset の書式
void* memset(void* addr, int val, size_t len);引数の意味
| 引数 | 内容 |
|---|---|
| addr | 書き込み先の先頭アドレス |
| val | 書き込む値(1バイト分) |
| len | 書き込むバイト数 |
戻り値
- addr と同じアドレス
配列を memset で初期化してみよう
サンプルプログラム
プロジェクト名:10-8 ソースファイル名: sample10-8-2.c
#include <stdio.h>
#include <string.h>
int main(void)
{
int data[5];
memset(data, 0, sizeof(data));
printf("data[0]=%d\n", data[0]);
printf("data[4]=%d\n", data[4]);
return 0;
}実行結果
data[0]=0
data[4]=0memset の本当の意味を理解しよう
ここで大事なポイントです。
memset は、
- 要素単位
ではなく - バイト単位
で書き込みます。
そのため、
- 0 で埋める → 安全
- 0以外で埋める → 型によっては危険
という特徴があります。
よくある注意点
- int配列を 1 で埋めても、すべて 1 になるとは限らない。
- ポインタや構造体の初期化には慎重になる。
👉 memset は基本的に 0 初期化専用
と考えるのが安全です。
メモリ比較・初期化関数の使いどころ
ここまでの内容をまとめます。
| 関数 | 役割 |
|---|---|
| memcmp | メモリ内容の等価判定 |
| memset | メモリ領域の一括初期化 |
どちらも、
- 配列
- バッファ
- 生のメモリ
を扱う 低レベルで強力な関数 です。
C言語らしい心構え
これらの関数はとても便利ですが、
- サイズ指定を間違える。
- 構造体に使ってしまう。
- 意味を理解せず使う。
と、簡単にバグの温床になります。
C言語では常に、
何バイトを、どこに、何の目的で操作しているか
を意識することが大切です。
