名前空間
変種
操作

memmove, memmove_s

From cppreference.com
< c‎ | string‎ | byte
ヘッダー <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) 全体をゼロで埋め(destdestsz の両方が有効な場合)、現在インストールされている 制約ハンドラ関数を呼び出します。
  • dest または src がヌルポインタである
  • destsz または countRSIZE_MAX より大きい
  • countdestsz より大きい(バッファオーバーフローが発生する)
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

[編集] 関連項目

あるバッファを別のバッファにコピーする
(関数) [編集]
オーバーラップしている可能性のある2つの配列間で、指定された数のワイド文字をコピーする
(関数) [編集]
C++ documentation for memmove
English 日本語 中文(简体) 中文(繁體)