Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語で独自のmemcpy()関数を自作する方法

この記事では、C言語で標準ライブラリのmemcpy()関数と同等の機能を自前で実装する方法を解説します。memcpy()は、あるメモリ領域から別のメモリ領域へデータブロックをコピーするための関数であり、文字列や配列など任意のデータの複製に広く使われています。

memcpy()の基本構文

まず、標準ライブラリにおけるmemcpy()のプロトタイプを確認しておきましょう。

void *memcpy(void *dest, const void *src, size_t num);
  • dest:コピー先のメモリ領域へのポインタ
  • src:コピー元のメモリ領域へのポインタ(const修飾により書き換え不可)
  • num:コピーするバイト数

自作memcpy()の実装方針

独自のmemcpy()を作成するポイントは、引数として受け取った汎用ポインタ(void*)をchar*型にキャストすることです。char型は必ず1バイトであることが規格で保証されているため、charポインタ経由でアクセスすれば、どのような型のデータでも1バイト単位で確実にコピーできます。あとはforループを使い、指定されたバイト数分だけソースからデスティネーションへ順番にデータを転送していきます。

実装例

以下のコードでは、custom_memcpy()という関数を定義し、文字列とint型配列の両方に対して動作を確認しています。

#include<stdio.h>
#include<string.h>

void custom_memcpy(void *dest, void *src, size_t n) {
    int i;
    // srcとdestをchar*にキャスト
    char *src_char = (char *)src;
    char *dest_char = (char *)dest;
    for (i = 0; i < n; i++)
        dest_char[i] = src_char[i]; // 1バイトずつ内容をコピー
}

main() {
    // 文字列のコピー例
    char src[] = "Hello World";
    char dest[100];
    custom_memcpy(dest, src, strlen(src) + 1); // 終端の'\0'も含めてコピー
    printf("The copied string is %s\n", dest);

    // int型配列のコピー例
    int arr[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
    int n = sizeof(arr) / sizeof(arr[0]);
    int dest_arr[n], i;
    custom_memcpy(dest_arr, arr, sizeof(arr));
    printf("The copied array is ");
    for (i = 0; i < n; i++)
        printf("%d ", dest_arr[i]);
}

実行結果

The copied string is Hello World
The copied array is 10 20 30 40 50 60 70 80 90

文字列の場合はstrlen(src) + 1とすることで、文字列終端のNULL文字('\0')まで含めてコピーしている点に注意してください。配列の場合はsizeof(arr)で配列全体のサイズ(バイト数)を取得することで、全要素をまとめて複製できます。

実装時の注意点

  • メモリ領域の重複には非対応: 本実装のように前方から順にコピーする方式では、コピー元とコピー先の領域が重なっている場合、正しく動作しません。重複が起こりうる場合はmemmove()を使用する必要があります。
  • コピー先の容量確保: dest側のバッファがnumバイト以上あることを呼び出し側で保証しなければ、バッファオーバーフローが発生します。
  • パフォーマンス: 実際の標準ライブラリ実装では、1バイトごとのループではなく、CPUのワード幅(4バイトや8バイト)単位での一括転送など、高速化のための最適化が施されています。
  1. Rubyで学ぶ!シーザー暗号エンコーダーの自作方法

    シーザー暗号(Caesar cipher)をご存知ですか? これは、ユリウス・カエサルが敵に知られないよう秘密のメッセージを隠すために実際に使った暗号化手法です。 シーザー暗号は、最も原始的な暗号技術の一つとされています。 その仕組みの核心は、アルファベットの文字をx個分だけずらす(ローテートする)というシンプルなアイデアにあります。 例えば x = 1 の場合、「A」は「B」に、「C」は「D」に変換されます。以下同様です。 では、これをコードで実装するにはどうすればよいのでしょうか? 答えは意外と簡単です。文字は数値(ASCIIコード)として表現できるという事実を利用すれば、文字の回転処理

  2. ブラウザ拡張機能の作り方を徹底解説【サンプルプロジェクト付き】

    この記事では、ブラウザ拡張機能とは何か、どのように動作するのか、そして自分でオリジナルの拡張機能を作る方法について解説します。記事の最後には、実際に「ワンクリックでコードスニペットをクリップボードにコピーできる」拡張機能を作成します。とても楽しい内容ですよ!この記事を読み進めるには、以下が必要です。JavaScriptの基本的な知識Firefoxブラウザ(他のブラウザでも可)ブラウザ拡張機能とは?ブラウザ拡張機能とは、ブラウザに追加することでその機能を拡張し、閲覧体験を向上させるツールのことです。例えば、デバイスにインストールした広告ブロッカーを思い浮かべてください。Webを閲覧する際に広告を