memmove, memmove_s
|
Определено в заголовке
<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) |
-
- dest или src является нулевым указателем
- destsz или count превышает RSIZE_MAX
- count превышает destsz (произойдет переполнение буфера)
-
Как и все функции с проверкой границ,
memmove_sгарантированно доступна только если реализация определяет __STDC_LIB_EXT1__ и если пользователь определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1 перед включением <string.h> .
Содержание |
Параметры
| dest | - | указатель на объект для копирования |
| destsz | - | максимальное количество байт для изменения в назначении (обычно размер объекта назначения) |
| src | - | указатель на объект для копирования |
| count | - | количество байт для копирования |
Возвращаемое значение
Примечания
memmove
может использоваться для установки
эффективного типа
объекта, полученного с помощью функции выделения памяти.
Несмотря на то, что функция описана «как если бы» использовался временный буфер, реальные реализации этой функции не несут накладных расходов на двойное копирование или дополнительную память. Распространённый подход (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); // нарушение строгого алиасинга 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); // количество больше чем 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 Функция memmove (стр.: TBD)
-
- K.3.7.1.2 Функция memmove_s (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 7.24.2.2 Функция memmove (стр. 264)
-
- K.3.7.1.2 Функция memmove_s (стр. 446)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 7.24.2.2 Функция memmove (стр. 363)
-
- K.3.7.1.2 Функция memmove_s (стр. 615)
- Стандарт C99 (ISO/IEC 9899:1999):
-
- 7.21.2.2 Функция memmove (стр: 326)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
-
- 4.11.2.2 Функция memmove
Смотрите также
|
(C11)
|
копирует один буфер в другой
(функция) |
|
(C95)
(C11)
|
копирует определённое количество широких символов между двумя, возможно перекрывающимися, массивами
(функция) |
|
C++ documentation
для
memmove
|
|