memcpy, memcpy_s
From cppreference.net
|
ヘッダーで定義
<string.h>
|
||
| (1) | ||
|
void
*
memcpy
(
void
*
dest,
const
void
*
src,
size_t
count
)
;
|
(C99まで) | |
|
void
*
memcpy
(
void
*
restrict
dest,
const
void
*
restrict
src,
size_t
count
)
;
|
(C99以降) | |
|
errno_t memcpy_s
(
void
*
restrict
dest, rsize_t destsz,
const void * restrict src, rsize_t count ) ; |
(2) | (C11以降) |
1)
src
が指すオブジェクトから
dest
が指すオブジェクトへ
count
文字をコピーします。両オブジェクトは
unsigned
char
の配列として解釈されます。
dest
配列の終端を超えてアクセスが発生した場合、動作は未定義です。オブジェクトが重複している場合
(これは
restrict
契約の違反です)
(C99以降)
、動作は未定義です。
dest
または
src
が無効なポインタまたはnullポインタである場合、動作は未定義です。
2)
(1)
と同様であるが、以下のエラーが実行時に検出され、
[
dest, dest
+
destsz
)
の宛先範囲全体をゼロクリアする(
dest
と
destsz
の両方が有効な場合)。さらに、現在インストールされている
constraint handler
関数を呼び出す:
-
-
destまたはsrcがヌルポインタである -
destszまたはcountが RSIZE_MAX より大きい -
countがdestszより大きい(バッファオーバーフローが発生する) - ソースと宛先のオブジェクトが重複している
-
dest
が指す文字配列のサイズが
count
<=
destsz
の場合、動作は未定義です。言い換えれば、
destsz
の誤った値は差し迫ったバッファオーバーフローを露呈しません。
-
すべての境界チェック付き関数と同様に、
memcpy_sは実装によって __STDC_LIB_EXT1__ が定義され、かつユーザーが <string.h> をインクルードする前に __STDC_WANT_LIB_EXT1__ を整数定数 1 に定義した場合にのみ利用可能であることが保証されます。
目次 |
パラメータ
| dest | - | コピー先オブジェクトへのポインタ |
| destsz | - | コピー先で変更可能な最大バイト数(通常はコピー先オブジェクトのサイズ) |
| src | - | コピー元オブジェクトへのポインタ |
| count | - | コピーするバイト数 |
戻り値
1)
dest
のコピーを返します
2)
成功時はゼロを返し、エラー時は非ゼロの値を返す。またエラー時、
dest
がnullポインタでなく、
destsz
が有効な場合、宛先配列に
destsz
バイトのゼロを書き込む。
注記
memcpy
は、割り当て関数によって取得されたオブジェクトの
effective type
を設定するために使用される場合があります。
memcpy
はメモリ間コピーにおいて最速のライブラリルーチンです。通常、
strcpy
がコピーするデータをスキャンする必要がある場合や、
memmove
が重複する入力の処理に予防措置を講じる必要がある場合よりも効率的です。
いくつかのCコンパイラは、適切なメモリコピーループを
memcpy
呼び出しに変換します。
strict aliasing
が同じメモリを異なる2つの型の値として検査することを禁止する場合、
memcpy
を使用して値を変換することができます。
例
このコードを実行
#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 source[] = "once upon a midnight dreary...", dest[4]; memcpy(dest, source, sizeof dest); for(size_t n = 0; n < sizeof dest; ++n) putchar(dest[n]); // 割り当てられたメモリの実効型をintに設定 int *p = malloc(3*sizeof(int)); // 割り当てられたメモリには実効型がない int arr[3] = {1,2,3}; memcpy(p,arr,3*sizeof(int)); // 割り当てられたメモリに実効型が設定された // データの再解釈 double d = 0.1; // int64_t n = *(int64_t*)(&d); // strict aliasing violation int64_t n; memcpy(&n, &d, sizeof d); // OK printf("\n%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 = memcpy_s(dst,sizeof dst,src,5); printf("dst = \"%s\", r = %d\n", dst,r); r = memcpy_s(dst,5,src,10); // countが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 }
出力例:
once 0x1.999999999999ap-4 is 3fb999999999999a as an int64_t dst = "aaaaayxyxy", r = 0 dst = "\0\0\0\0\0yxyxy", r = 22
参考文献
- C11標準 (ISO/IEC 9899:2011):
-
- 7.24.2.1 memcpy関数 (p: 362)
-
- K.3.7.1.1 memcpy_s関数 (p: 614)
- C99標準 (ISO/IEC 9899:1999):
-
- 7.21.2.1 memcpy関数 (p: 325)
- C89/C90標準 (ISO/IEC 9899:1990):
-
- 4.11.2.1 memcpy関数
関連項目
|
(C23)
|
指定された区切り文字の後に停止しながら、一方のバッファを他方にコピーする
(関数) |
|
(C11)
|
一方のバッファを他方に移動する
(関数) |
|
(C95)
(C11)
|
重複しない2つの配列間で指定量のワイド文字をコピーする
(関数) |
|
C++ドキュメント
for
memcpy
|
|