C言語における主要なメモリ操作関数の解説と実装

memcpy は、指定されたバイト数に従ってソース領域からデスティネーション領域へデータを非破壊的に複製する関数です。以下はその自作実装例です:

void* my_memcpy(void* dst, const void* src, size_t n) {
    if (!dst || !src) return NULL;
    unsigned char* d = (unsigned char*)dst;
    const unsigned char* s = (const unsigned char*)src;
    for (size_t i = 0; i < n; ++i) {
        d[i] = s[i];
    }
    return dst;
}

この実装では、unsigned char* へのキャストにより1バイト単位のアクセスを可能にし、任意の型のデータを安全に転送できます。たとえば、int 配列5要素(20バイト)をコピーすると、元の値がそのまま転送されます。

memmove は、memcpy の拡張版であり、ソースとデスティネーション領域が重なる場合でも正しく動作します。重複領域へのコピーでは、方向性が重要です:

  • デスティネーションがソースより前にある → 前方からコピー(上書きリスク回避)
  • デスティネーションがソースより後にある → 後方からコピー(既存データ保護)

以下はその条件付き実装:

void* my_memmove(void* dst, const void* src, size_t n) {
    if (!dst || !src || n == 0) return dst;
    unsigned char* d = (unsigned char*)dst;
    const unsigned char* s = (const unsigned char*)src;

    if (d < s) {
        // ソースがデスティネーションより後 → 前方から
        for (size_t i = 0; i < n; ++i) {
            d[i] = s[i];
        }
    } else {
        // ソースがデスティネーションより前 → 後方から
        for (size_t i = n; i > 0; --i) {
            d[i-1] = s[i-1];
        }
    }
    return dst;
}

memset は、指定アドレスから始まる n バイトを特定の値で初期化する関数です。たとえば、int arr[10] 全体(40バイト)をゼロで埋めるには:

memset(arr, 0, sizeof(arr));

第2引数は int ではなく unsigned char として解釈されるため、値は0〜255の範囲で指定します。

memcmp は、2つのメモリ領域をバイト単位で比較し、差分が発生した最初の位置の符号付きバイト値を返します。戻り値は:

  • < 0:左側が辞書順で小さい
  • == 0:全バイトが一致
  • > 0:左側が辞書順で大きい
int result = memcmp(ptr_a, ptr_b, 16); // 先頭16バイトを比較

タグ: c-language Memory-Management memcpy memmove memset

6月4日 22:48 投稿