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) |
count символов из объекта, на который указывает src, в объект, на который указывает dest. Оба объекта рассматриваются как массивы unsignedchar. Объекты могут перекрываться: копирование выполняется так, как если бы символы сначала копировались во временный массив символов, а затем из этого массива в dest.dest или src является недопустимым или нулевым указателем.[dest, dest + destsz) (если dest и destsz являются допустимыми) и вызывает текущую установленную функцию обработчика ограничений: -
destилиsrcявляется нулевым указателем -
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 | - | количество байтов для копирования |
Возвращаемое значение
dest
dest не является нулевым указателем и destsz допустимо, записывает destsz нулевых байтов в массив назначения.Примечания
memmove можно использовать для задания эффективного типа объекта, полученного с помощью функции выделения памяти.
Несмотря на то, что функция специфицирована «как если бы» использовался временный буфер, её реальные реализации не несут затрат на двойное копирование и дополнительную память. Обычно (glibc и bsd libc) байты копируются вперёд от начала буфера, если область назначения начинается перед источником, и назад от конца в противном случае; если перекрытия нет, используется более эффективная функция memcpy.
Если строгая алиасинг-модель запрещает рассматривать одну и ту же область памяти как значения двух разных типов, для преобразования значений можно использовать 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 Функция 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++ для memmove |
|
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/string/byte/memmove