Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
memcpy() / memmove() / memset() / memcmp()
メモリブロックをバイト単位でコピー・初期化・比較する関数です。文字列に限らず任意のデータ型のメモリを直接操作できます。
構文
// src から dst へ n バイトコピーします(メモリが重なってはいけません)。 // 戻り値: dst のポインタ。 void *memcpy(void *dst, const void *src, size_t n); // src から dst へ n バイトコピーします(メモリが重なっても安全です)。 void *memmove(void *dst, const void *src, size_t n); // s の先頭 n バイトを値 c(0〜255)で埋めます。 void *memset(void *s, int c, size_t n); // s1 と s2 の先頭 n バイトを比較します。 // 戻り値: s1 < s2 なら負、等しければ 0、s1 > s2 なら正。 int memcmp(const void *s1, const void *s2, size_t n);
関数比較
| 関数 | 用途 | 重複領域 | 概要 |
|---|---|---|---|
| memcpy() | コピー | 不可 | 高速コピーです。src と dst が重なる場合は memmove() を使います。 |
| memmove() | コピー | 可 | 重複を考慮した安全なコピーです。memcpy() より若干遅い場合があります。 |
| memset() | 初期化 | — | バッファの全体をゼロまたは特定バイト値で埋めます。 |
| memcmp() | 比較 | — | バイナリデータの等値比較に使います。文字列以外のデータに有効です。 |
サンプルコード
#include <stdio.h>
#include <string.h>
typedef struct { int x; int y; } Point;
int main(void) {
// memcpy で構造体をコピーします。
Point p1 = {10, 20};
Point p2;
memcpy(&p2, &p1, sizeof(Point));
printf("p2: x=%d, y=%d\n", p2.x, p2.y); // 『p2: x=10, y=20』と出力されます。
// memset でバッファをゼロで初期化します。
int arr[5];
memset(arr, 0, sizeof(arr));
printf("arr[0]=%d, arr[4]=%d\n", arr[0], arr[4]); // 全要素が 0 です。
// memset で配列を特定の値で埋めます(バイト値に注意します)。
unsigned char buf[4];
memset(buf, 0xFF, sizeof(buf));
printf("buf: %02X %02X %02X %02X\n", buf[0], buf[1], buf[2], buf[3]);
// 『FF FF FF FF』と出力されます。
// memmove で重なるメモリを安全にシフトします。
char s[] = "hello world";
memmove(s, s + 6, 5); // 『world』を先頭に移動します。
s[5] = '\0';
printf("memmove後: %s\n", s); // 『memmove後: world』と出力されます。
// memcmp でバイナリデータを比較します。
char a[] = {1, 2, 3};
char b[] = {1, 2, 3};
printf("memcmp: %d\n", memcmp(a, b, 3)); // 『memcmp: 0』と出力されます(等しい)。
return 0;
}
概要
memcpy() のコピー元と先が重なる場合は未定義動作になります。同一バッファ内で部分的にずらしてコピーするような処理では必ず memmove() を使ってください。
memset() で int 配列を 0 以外の値に初期化する場合、バイト値で埋められるため意図した値にならないことがあります。例えば『memset(arr, 1, sizeof(arr))』では各要素は 0x01010101(16进数)になります。整数ゼロ(0x00000000)への初期化は正しく動作します。
動的確保直後のゼロ初期化には calloc() を使う方が簡潔です。詳細は『malloc() / free()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。