memmove, memmove_s
提供: cppreference.com
ヘッダ <string.h> で定義 | ||
void* memmove(void* dest, constvoid* src, size_t count ); | (1) | |
errno_t memmove_s(void*dest, rsize_t destsz, constvoid*src, rsize_t count); | (2) | (C11以上) |
1)
src
の指すオブジェクトから dest
の指すオブジェクトに count
個の文字をコピーします。 どちらのオブジェクトも unsignedchar の配列として再解釈されます。 オブジェクトはオーバーラップしても構いません。 コピーは、文字が一時的な文字配列にコピーされ、その後その配列から dest
にコピーされたかのように、行われます。dest
配列の終端を超えてアクセスが発生する場合、動作は未定義です。 dest
または src
が無効またはヌルポインタの場合、動作は未定義です。2)(1) と同じですが、以下のエラーを実行時に検出した場合、 (
dest
と destsz
がどちらも有効であれば) コピー先の範囲 [dest, 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 | - | コピーするバイト数 |
[編集]戻り値
1)
dest
のコピーを返します。2) 成功した場合はゼロ、エラーが発生した場合は非ゼロの値を返します。 また、エラーの場合、
dest
がヌルポインタでなく destsz
が有効であれば、 destsz
個のゼロのバイトをコピー先の配列に書き込みます。[編集]ノート
memmove
は確保関数で取得したオブジェクトの実効型を設定するために使用することができます。
一時的なバッファを使用する「かのように」と規定されているにもかかわらず、この関数の実際の実装は二回のコピーや余分なメモリのオーバーヘッドを負担しません。 一般的な手法 (glibc および bsd libc) は、コピー先がコピー元より前に始まるならばバッファの先頭から順方向に、そうでなければ末尾から逆方向にバイトをコピーし、オーバーラップがまったくないときは memcpy にフォールバックします。
厳格なエイリアシングにより同じメモリを2つの異なる型の値として調べることが禁止される場合に、値を変換するために memmove
を使用することができます。
[編集]例
Run this code
#define __STDC_WANT_LIB_EXT1__ 1#include <stdio.h>#include <stdint.h>#include <inttypes.h>#include <string.h>#include <stdlib.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 intint*p =malloc(3*sizeof(int));// allocated memory has no effective typeint arr[3]={1,2,3}; memmove(p,arr,3*sizeof(int));// allocated memory now has an effective type // reinterpreting datadouble d =0.1;// int64_t n = *(int64_t*)(&d); // strict aliasing violationint64_t n; memmove(&n, &d, sizeof d);// OKprintf("%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
[編集]参考文献
- C11 standard (ISO/IEC 9899:2011):
- 7.24.2.2 The memmove function (p: 363)
- K.3.7.1.2 The memmove_s function (p: 615)