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