memmove, memmove_s
From cppreference.net
|
헤더 파일에 정의됨
<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)
src
가 가리키는 객체로부터
dest
가 가리키는 객체로
count
개의 문자를 복사합니다. 두 객체 모두
unsigned
char
배열로 해석됩니다. 객체들은 중첩될 수 있습니다: 문자가 임시 문자 배열로 복사된 후, 해당 배열에서
dest
로 문자가 복사되는 것처럼 동작합니다.
dest 배열의 끝을 넘어서 접근이 발생하면 동작은 정의되지 않습니다.
dest
또는
src
가 유효하지 않거나 null 포인터인 경우에도 동작은 정의되지 않습니다.
2)
(1)
과 동일하지만, 런타임에 다음 오류를 감지할 경우 전체 대상 범위
[
dest, dest
+
destsz
)
를 0으로 채우고(
dest
와
destsz
가 모두 유효한 경우) 현재 설치된
constraint handler
함수를 호출합니다:
-
- dest 또는 src 가 null 포인터인 경우
- destsz 또는 count 가 RSIZE_MAX 보다 큰 경우
- count 가 destsz 보다 큰 경우 (버퍼 오버플로우가 발생할 경우)
dest
가 가리키는 문자 배열의 크기가
count
<
destsz
인 경우 동작은 정의되지 않습니다. 즉,
destsz
의 잘못된 값은 임박한 버퍼 오버플로우를 노출하지 않습니다.
-
모든 경계 검사 함수와 마찬가지로,
memmove_s는 구현체가 __STDC_LIB_EXT1__ 를 정의하고, 사용자가 __STDC_WANT_LIB_EXT1__ 를 정수 상수 1 으로 정의한 후 <string.h> 를 포함할 경우에만 사용 가능함이 보장됩니다.
목차 |
매개변수
| dest | - | 복사 대상 객체를 가리키는 포인터 |
| destsz | - | 대상에서 수정할 최대 바이트 수 (일반적으로 대상 객체의 크기) |
| src | - | 복사 원본 객체를 가리키는 포인터 |
| count | - | 복사할 바이트 수 |
반환값
1)
dest
의 복사본을 반환합니다
2)
성공 시 0을 반환하고 오류 시 0이 아닌 값을 반환합니다. 또한 오류 발생 시,
dest
가 null 포인터가 아니고
destsz
가 유효한 경우,
destsz
개의 제로 바이트를 대상 배열에 기록합니다.
참고 사항
memmove
는 할당 함수로 얻은 객체의
effective type
을 설정하는 데 사용될 수 있습니다.
"임시 버퍼가 사용되는 것처럼" 지정되었지만, 이 함수의 실제 구현에서는 오버헤드나 이중 복사 또는 추가 메모리가 발생하지 않습니다. 일반적인 접근 방식(glibc 및 bsd libc)은 대상이 소스보다 앞서 시작하는 경우 버퍼의 시작부터 앞으로 바이트를 복사하고, 그렇지 않은 경우 끝에서 뒤로 복사하며, 겹침이 전혀 없는 경우에는 더 효율적인 memcpy 로 대체됩니다.
strict aliasing
이 서로 다른 두 타입의 값으로 동일한 메모리를 검사하는 것을 금지하는 경우,
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); // [4,5,6]에서 [5,6,7]로 복사 puts(str); // 할당된 메모리의 유효 타입을 int로 설정 int* p = malloc(3 * sizeof(int)); // 할당된 메모리는 유효 타입이 없음 int arr[3] = {1, 2, 3}; memmove(p, arr, 3 * sizeof(int)); // 할당된 메모리에는 이제 유효 타입이 있음 // 데이터 재해석 double d = 0.1; // int64_t n = *(int64_t*)(&d); // strict aliasing 위반 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가 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 memmove 함수 (p: 264)
-
- K.3.7.1.2 memmove_s 함수 (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 memmove 함수 (p: 326)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 4.11.2.2 The memmove function
참고 항목
|
(C11)
|
버퍼를 다른 버퍼로 복사
(함수) |
|
(C95)
(C11)
|
두 배열(겹칠 수 있음) 사이에서 지정된 개수의 와이드 문자를 복사
(함수) |
|
C++ documentation
for
memmove
|
|