memmove, memmove_s
From cppreference.com
| ヘッダー <string.h> で定義 |
||
| void* memmove( void* dest, const void* src, size_t count ); |
(1) | |
| errno_t memmove_s(void* dest, rsize_t destsz, const void* src, rsize_t count); |
(2) | (C11 以降) |
1) count 文字を src が指すオブジェクトから dest が指すオブジェクトへコピーします。両方のオブジェクトは unsigned char の配列として解釈されます。オブジェクトは重なっていても構いません。コピーは、文字が一時的な文字配列にコピーされ、次にその配列から dest にコピーされるかのように行われます。
dest 配列の末尾を超えてアクセスが発生した場合、動作は未定義です。dest または src のいずれかが無効なポインタまたはヌルポインタである場合、動作は未定義です。
2) (1) と同じですが、実行時に以下のエラーを検出した場合、宛先範囲 [dest, dest + destsz) 全体をゼロで埋め(dest と destsz の両方が有効な場合)、現在インストールされている 制約ハンドラ関数を呼び出します。
- dest または src がヌルポインタである
- destsz または count が RSIZE_MAX より大きい
- count が destsz より大きい(バッファオーバーフローが発生する)
dest が指す文字配列のサイズ < count <= destsz の場合、動作は未定義です。言い換えれば、destsz の誤った値は、差し迫ったバッファオーバーフローを露呈させません。
- すべての境界チェック付き関数と同様に、
memmove_sは、実装によって __STDC_LIB_EXT1__ が定義され、ユーザーが <string.h> をインクルードする前に __STDC_WANT_LIB_EXT1__ を整数定数 1 に定義した場合にのみ利用可能であることが保証されます。
目次 |
[編集] パラメータ
| dest | - | コピー先のオブジェクトへのポインタ |
| destsz | - | 宛先で変更する最大バイト数(通常、宛先オブジェクトのサイズ) |
| src | - | コピー元のオブジェクトへのポインタ |
| count | - | count |
[編集] 戻り値
1) dest のコピーを返します。
2) 成功した場合はゼロを返し、エラーの場合は非ゼロの値を返します。また、エラーが発生した場合、dest がヌルポインタでなく、destsz が有効である場合、宛先配列に destsz バイトのゼロを書き込みます。
[編集] 備考
memmove は、割り当て関数によって取得されたオブジェクトの実効型を設定するために使用できます。
一時バッファが使用される「かのように」指定されているにもかかわらず、この関数の実際の実装では、オーバーヘッドや二重コピー、追加メモリは発生しません。一般的なアプローチ(glibc と bsd libc)は、宛先がソースの前に始まる場合はバッファの先頭からバイトを順方向にコピーし、そうでない場合は末尾から逆方向にコピーします。まったく重なりがない場合は、より効率的な memcpy にフォールバックします。
厳密なエイリアシングが同じメモリを2つの異なる型の値として調査することを禁止している場合、memmove を使用して値を変換することができます。
[編集] 例
このコードを実行
#define __STDC_WANT_LIB_EXT1__ 1 #include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char str[] = "1234567890"; puts(str); memmove(str + 4, str + 3, 3); // copy from [4,5,6] to [5,6,7] puts(str); // setting effective type of allocated memory to be int int* p = malloc(3 * sizeof(int)); // allocated memory has no effective type int arr[3] = {1, 2, 3}; memmove(p, arr, 3 * sizeof(int)); // allocated memory now has an effective type // reinterpreting data double d = 0.1; // int64_t n = *(int64_t*)(&d); // strict aliasing violation int64_t n; memmove(&n, &d, sizeof d); // OK printf("%a is %" PRIx64 " as an int64_t\n", d, n); #ifdef __STDC_LIB_EXT1__ set_constraint_handler_s(ignore_handler_s); char src[] = "aaaaaaaaaa"; char dst[] = "xyxyxyxyxy"; int r = memmove_s(dst, sizeof dst, src, 5); printf("dst = \"%s\", r = %d\n", dst, r); r = memmove_s(dst, 5, src, 10); // count is greater than destsz printf("dst = \""); for (size_t ndx = 0; ndx < sizeof dst; ++ndx) { char c = dst[ndx]; c ? printf("%c", c) : printf("\\0"); } printf("\", r = %d\n", r); #endif }
実行結果の例
1234567890 1234456890 0x1.999999999999ap-4 is 3fb999999999999a as an int64_t dst = "aaaaayxyxy", r = 0 dst = "\0\0\0\0\0yxyxy", r = 22
[編集] 参照
- C23標準 (ISO/IEC 9899:2024)
- 7.24.2.2 The memmove function (p: TBD)
- K.3.7.1.2 The memmove_s function (p: TBD)
- C17標準 (ISO/IEC 9899:2018)
- 7.24.2.2 The memmove function (p: 264)
- K.3.7.1.2 The memmove_s function (p: 446)
- C11標準 (ISO/IEC 9899:2011)
- 7.24.2.2 The memmove function (p: 363)
- K.3.7.1.2 The memmove_s function (p: 615)
- C99標準 (ISO/IEC 9899:1999)
- 7.21.2.2 The memmove function (p: 326)
- C89/C90標準 (ISO/IEC 9899:1990)
- 4.11.2.2 The memmove function
[編集] 関連項目
| (C11) |
あるバッファを別のバッファにコピーする (関数) |
| (C95)(C11) |
オーバーラップしている可能性のある2つの配列間で、指定された数のワイド文字をコピーする (関数) |
| C++ documentation for memmove
| |