C++でmemcpy()とmemmove()を自作して実装する方法
memcpy()関数とは
memcpy()は、指定されたサイズ分のデータをコピー元(source)からコピー先(destination)へ複製するための標準ライブラリ関数です。
memcpy関数のプロトタイプは次の通りです。
void * memcpy(void *destination_location, void *source_location, size_t size)
自作memcpy()の実装
ここでは、データを1バイト(1文字)ずつコピー元からコピー先へ順番に転送するシンプルな実装を紹介します。
#include<stdio.h>
#include<string.h>
void MemcpyFunc(void *dest, void *src, size_t n){
char *dataS = (char *)src;
char *dataD = (char *)dest;
for (int i = 0; i < n; i++)
dataD[i] = dataS[i];
}
int main() {
char dataS[] = "Hello!";
char dataD[100];
MemcpyFunc(dataD, dataS, strlen(dataS) + 1);
printf("Copied string is %s", dataD);
return 0;
}出力:
Copied string is Hello!
memmove()関数とは
memmove()もmemcpy()と同様に、データを1文字ずつコピー元からコピー先へ転送する関数です。両者の違いは、コピー元とコピー先のメモリ領域が重なっている(オーバーラップしている)場合の動作にあります。memcpy()は領域が重なると正しく動作しない可能性がありますが、memmove()はそのようなケースでも安全に動作するように設計されています。
自作memmove()の実装
この実装では、まずデータを一時配列(temp)にコピーしてから、改めてコピー先へ転送します。一時バッファを介することで、コピー元とコピー先が重なっていても、途中でデータが上書きされることによる破壊を防げます。
#include<stdio.h>
#include<string.h>
void MemmoveFunc(void *dest, void *src, size_t n){
char *dataS = (char *)src;
char *dataD = (char *)dest;
char *temp = new char[n];
for (int i = 0; i < n; i++)
temp[i] = dataS[i];
for (int i = 0; i < n; i++)
dataD[i] = temp[i];
delete[] temp;
}
int main() {
char dataS[] = "Hello!";
char dataD[100];
MemmoveFunc(dataD, dataS, strlen(dataS) + 1);
printf("Moved string is %s", dataD);
return 0;
}出力:
Moved string is Hello!
まとめ
memcpy()はシンプルで高速ですが、コピー元とコピー先のメモリ領域が重なる場合には未定義動作となる恐れがあります。一方、memmove()は一時バッファを経由することでオーバーラップの問題を回避できます。実際の開発では、領域が重なる可能性があるかどうかを見極めて、適切な方の関数を選択することが重要です。
-
C++でint・float・double・charのサイズを確認する方法|sizeof演算子の使い方を解説
C++における主なデータ型C++には多数のデータ型が用意されていますが、その中でも特によく使用されるのが「int」「float」「double」「char」の4つです。それぞれの特徴は以下のとおりです。int:整数を扱うためのデータ型です。通常は4バイトのメモリ領域を必要とします。float:単精度浮動小数点数(小数)を格納するためのデータ型です。通常は4バイトのメモリ領域を使用します。double:倍精度浮動小数点数(より高精度な小数)を格納するためのデータ型です。通常は8バイトのメモリ領域を使用します。char:1文字を格納するためのデータ型です。通常は1バイトのメモリ領域を使用します。s
-
Rubyで学ぶ!シーザー暗号エンコーダーの自作方法
シーザー暗号(Caesar cipher)をご存知ですか? これは、ユリウス・カエサルが敵に知られないよう秘密のメッセージを隠すために実際に使った暗号化手法です。 シーザー暗号は、最も原始的な暗号技術の一つとされています。 その仕組みの核心は、アルファベットの文字をx個分だけずらす(ローテートする)というシンプルなアイデアにあります。 例えば x = 1 の場合、「A」は「B」に、「C」は「D」に変換されます。以下同様です。 では、これをコードで実装するにはどうすればよいのでしょうか? 答えは意外と簡単です。文字は数値(ASCIIコード)として表現できるという事実を利用すれば、文字の回転処理