memcpy関数 - メモリ領域をバイト単位でコピーする

memcpy関数は、メモリ領域をバイト単位でコピーする関数です。「string.h」をインクルードします。

#include <string.h>

void *memcpy(void *buf1, const void *buf2, size_t n);

第一引数はコピー先のアドレスです。汎用ポインタ型ですので、どのポインタ型でも大丈夫です。

第二引数はコピー元のアドレスです。汎用ポインタ型ですので、どのポインタ型でも大丈夫です。

第三引数にバイトサイズを指定します。size_t型です。int32_t型までの範囲で0以上の数値であれば、まず安心です。0の指定は有効な引数で、この場合コピーは行われません。

コピー先とコピー元のデータ領域が重なっていた場合には、動作は保証されません。コピー先とコピー元のデータ領域が重なっていた場合でも正しく動作させる場合はmemmove関数を使用してください。重ならない場合は、性能が優先されるmemcpy関数を使いましょう。

文字列をコピーする

memcpy関数で文字列をコピーするサンプルです。strlen関数で、文字列の長さを取得、calloc関数で、メモリ領域を確保、その領域にmemcpy関数でコピーという処理を行っています。コピー先の変数にconst修飾子がついていると、コピーできないので、const修飾子がつかない一時的な文字列にコピーしています。

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

int main(void) {
  // 文字列
  const char* message = "Hello";
  
  // 文字列の長さ
  int32_t message_length = strlen(message);
  
  // メモリ領域を確保
  char* new_message_tmp = calloc(sizeof(char), message_length + 1);
  
  // memcpy関数で一時的な文字列にコピー
  memcpy(new_message_tmp, message, message_length);
  
  // 新しい文字列に代入(const修飾子をつけたいので)
  const char* new_message = new_message_tmp;
  new_message_tmp = NULL;
  
  printf("%s\n", new_message);
}

出力結果です。

Hello

符号あり32bit整数の配列をコピーする

memcpy関数でint32_t - 符号あり32bit整数配列をコピーするサンプルです。calloc関数で、メモリ領域を確保、その領域にmemcpy関数でコピーという処理を行っています。コピーする長さは「要素の型のサイズ × 配列の長さ」になることに注意してください。for文で、配列の要素を出力しています。

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

int main(void) {
  // 配列
  int32_t nums_length = 3;
  int32_t nums[] = {3, 5, 7};
  
  // メモリ領域を確保
  int32_t* new_nums = calloc(sizeof(int32_t), nums_length);
  
  // memcpy関数でint32_t型の配列をコピー
  memcpy(new_nums, nums, sizeof(int32_t) * nums_length);
  
  for (int32_t i = 0; i < nums_length; i++) {
    printf("nums[%d]: %d\n", i, new_nums[i]);
  }
}

出力結果です。

nums[0]: 3
nums[1]: 5
nums[2]: 7

関連情報