C 言語で文字列配列をコピーする
この記事では、C 言語で文字列配列をコピーする方法について、複数の方法を紹介します。
C 言語で文字列配列をコピーするには memcpy
関数を使用する
char
配列はおそらく C 言語のコードで操作される最も一般的なデータ構造であり、配列の内容をコピーすることはそのための中核的な操作の一つです。C 言語の文字列は char
配列と非常によく似ているので、配列の内容をコピーする方法は複数ある。次の例では、arr
と arr2
という 2つの配列を宣言しています。前者は文字リスト記法で初期化され、後者は文字列リテラルで初期化されています。前者は文字リスト記法で初期化され、後者は文字列リテラルで初期化されます。arr
オブジェクトはメモリ上では 7 文字ですが、arr2
は 17 文字と終端のヌルバイトを加えた 18 バイトのオブジェクトになります。したがって、第 2 引数に sizeof arr2 - 1
式の値を渡して配列の長さを表すことになります。一方、arr2
の配列の内容を printf
関数と %s
書式指定子を用いて出力することもできます。
char
配列を別の場所にコピーする場合も、同じことを考慮しなければなりません。関数 memcpy
は、<string.h>
ヘッダファイルで定義されている標準ライブラリの文字列ユーティリティの一部です。この関数は 3つのパラメータを持ち、最初のパラメータはコピー先のポインタで、配列の内容がコピーされます。2 番目のパラメータはコピー元の配列へのポインタであり、最後のパラメータはコピーするバイト数を指定します。演算子 sizeof
は char
配列のオブジェクトサイズをバイト単位で返すことに注目してください。そこで、sizeof arr
式の値を渡して malloc
を呼び出して動的メモリを確保します。返されたメモリ領域は arr
の内容を保持するのに十分であり、バッファオーバーフローのバグを心配する必要はありません。ただし、malloc
から返されたポインタは解放されている必要があることに注意してください。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printCharArray(char *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
printf("%c, ", arr[i]);
}
printf("\n");
}
int main(int argc, char *argv[]) {
char arr[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
char arr2[] = "array initialized";
printf("%lu\n", sizeof arr);
printf("%lu\n", sizeof arr2);
printCharArray(arr, sizeof arr);
printCharArray(arr2, sizeof arr2 - 1);
char *str = malloc(sizeof arr);
memcpy(str, arr, sizeof arr);
printf("str: ");
printCharArray(str, sizeof arr);
free(str);
str = malloc(sizeof arr2);
memcpy(str, arr2, sizeof arr2);
printf("str: %s\n", str);
free(str);
exit(EXIT_SUCCESS);
}
出力:
7
18
a, b, c, d, e, f, g,
a, r, r, a, y, , i, n, i, t, i, a, l, i, z, e, d,
str: a, b, c, d, e, f, g,
str: array initialized
関数 memove
を用いて C 言語の文字列配列をコピーする
memove
は、標準ライブラリの文字列ユーティリティのもう一つのメモリ領域コピー関数です。これは、コピー先とコピー元のメモリ領域が重複している場合に対応するために、より堅牢な関数として実装されています。memove
のパラメータは memcpy
と同じです。
arr2
の内容をコピーする際には、3 番目のパラメータとして sizeof arr2
式を渡すようにした。つまり、終端の NULL バイトもコピー先のポインタにコピーされたことになるが、結果として、printCharArray
を使うよりも、printf
を%s
で呼び出して内容を出力することで、この動作を利用することになります。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printCharArray(char *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
printf("%c, ", arr[i]);
}
printf("\n");
}
int main(int argc, char *argv[]) {
char arr[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
char arr2[] = "array initialized";
char *str = malloc(sizeof arr);
memmove(str, arr, sizeof arr);
printf("str: ");
printCharArray(str, sizeof arr);
free(str);
str = malloc(sizeof arr2);
memmove(str, arr2, sizeof arr2);
printf("str: %s\n", str);
free(str);
exit(EXIT_SUCCESS);
}
出力:
str: a, b, c, d, e, f, g,
str: array initialized