Spec-Zone.ru › C

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)
1) Копирует count символов из объекта, на который указывает src, в объект, на который указывает dest. Оба объекта рассматриваются как массивы unsignedchar. Объекты могут перекрываться: копирование выполняется так, как если бы символы сначала копировались во временный массив символов, а затем из этого массива в dest.
Поведение не определено, если доступ выполняется за пределами массива dest. Поведение не определено, если dest или src является недопустимым или нулевым указателем.
2) То же, что и (1), за исключением того, что при обнаружении следующих ошибок во время выполнения функция обнуляет весь диапазон назначения [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 - количество байтов для копирования

Возвращаемое значение

1) Возвращает копию dest
2) При успешном выполнении возвращает ноль, а при ошибке — ненулевое значение. Кроме того, при ошибке, если 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

См. также

memcpymemcpy_s
(C11)
копирует один буфер в другой
(функция)
wmemmovewmemmove_s
(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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API