C LANGUAGE TECHNOLOGY

【C言語】memcpy関数とmemmove関数の違いと自作関数

悩んでいる人

C言語でmemcpy関数とmemmove関数の違いを教えて!

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOSの授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校コンピュータサイエンス学部2021年の世界大学学術ランキングで20位)で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発
  • プログラミング歴15年以上,習得している言語: C/C++Solidity,Java,Python,Ruby,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開

こういった私から学べます.

memcpy関数とmemmove関数の違い

memcpy関数は,メモリ領域srcの先頭nバイトをメモリ領域destにコピーします.

コピー元の領域とコピー先の領域が重なってはいけません.

正常にコピーできない可能性があり,未定義の動作になります.

memcpy関数の戻り値は,destへのポインタです.

memmove関数は,メモリ領域srcの先頭nバイトをメモリ領域destにコピーします.

memcpy関数とは異なり,memmove関数はコピー元とコピー先のメモリ領域が重なってもよいです.

最初にsrcのバイトがsrcともdestとも重ならない一時的な配列にコピーされてから,一時的な配列からdestにバイトのコピーが行われたかのように動作します.

※一時的な配列がなくてもmemmove関数は実装可能です.自作関数で紹介します.

その代わり,memmove関数はmemcpy関数より実行時間が長いというデメリットがあります.(実際には無視できるくらいです.)

memmove関数の戻り値は,destへのポインタです.

メモリ領域ではなく文字列をコピーするstrcpy関数の使い方を知りたいあなたはこちらからどうぞ.

C言語 strcpy関数
【C言語】strcpy/strncpy/strcpy_s関数の使い方と自作関数

こういった悩みにお答えします. こういった私から学べます. 目次1 strcpy関数1.1 strcpy関数の使い方1.2 strcpy関数の自作関数1.3 strcpy関数の注意点2 strncpy ...

続きを見る

memcpy関数とmemmove関数の利用例

memcpy関数とmemmove関数の利用例は以下になります.

GCCでコンパイルした場合の実行結果は以下になります.

3~4行目のsとtの文字列は,コピーするメモリ領域が重なっていないので,同じ「0123456789」になっていることがわかります.

5~6行目のmemcpy関数と7~8行目のmemove関数の結果は,コピーするメモリ領域が重なっているので異なる結果になると思ったのですが,同じ結果(それぞれ「0120123489」と「0123423489」)になっていますね...

GCCではmemcpy関数とmemmove関数が同じ結果になりました.

Clangでコンパイルした場合の実行結果は以下になります.

3~4行目と7~8行目の実行結果はGCCでコンパイルした場合と同様です.

5行目は「0120123189」で6行目は「0123123189」と,7~8行目とそれぞれ異なる結果になりました.

つまり,GCCとClangで動作結果が異なりますので,コピーするメモリ領域が重なる場合はmemmove関数を利用しましょう!

参考までにVisual Studioでビルドした場合の実行結果は以下になります.GCCと同様です.

memcpy関数とmemmove関数の自作関数

memcpy関数とmemmove関数の自作関数は以下になります.

mymemcpy関数はsrcの先頭からdestにコピーするため,コピーするメモリ領域が重なった場合(かつdestのアドレスがsrcのアドレスより大きい場合)は正常にコピーできません.

これに対して,mymemmove関数では,28行目のif文でdestのアドレスとsrcのアドレスを比較します.

destのアドレスsrcのアドレス以下の場合,srcの先頭からdestにコピーし,そうでなければsrcの末尾からdestにコピーします.

なので,mymemmove関数はコピーするメモリ領域が重なった場合でも正常にコピーできます.

実行結果は以下になります.

3~4行目と7~8行目の実行結果は同様です.

5行目は「0120120189」,6行目は「0120120189」と7~8行目とClangの場合と異なる結果になりましたが,正常にコピーできなかったという点は同様です.

まとめ

C言語でmemcpy関数とmemmove関数の違いと自作関数を紹介しました.

コピーするメモリ領域が重なった場合,memcpy関数とmemmove関数は,GCCとVisual Studioでは同じ結果,Clangでは異なる結果になりました.

memcpy関数とmemmove関数の違いは下表になります.

※実行速度の違いは実際には無視できるくらいです.

項目memcpy関数memmove関数
メモリ領域が重なった場合正常にコピーできない可能性がある
(未定義の動作)
GCC/Visual Studioは正常に動作
Clangは未定義の動作
正常にコピーできる
実行速度速い遅い

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

友だち追加

独学が難しいあなたは,C言語を学べるおすすめのオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , , , , , , , , ,