Spec-Zone.ru › C

memcpy, memcpy_s

Определено в заголовочном файле <string.h>
void* memcpy( void* dest, const void* src, size_t count );
(1) (до 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) Копирует count символов из объекта, на который указывает src, в объект, на который указывает dest. Оба объекта интерпретируются как массивы unsignedchar.
Поведение не определено, если доступ осуществляется за пределами массива dest. Если объекты перекрываются (что является нарушением контракта restrict)(начиная с C99), поведение не определено. Поведение не определено, если dest или src является недопустимым или нулевым указателем.
2) То же, что и (1), за исключением того, что следующие ошибки обнаруживаются во время выполнения и приводят к обнулению всего диапазона назначения [dest, dest + destsz) (если dest и destsz являются допустимыми), а также к вызову установленной в данный момент функции обработчика ограничений:
  • dest или src является нулевым указателем
  • destsz или count больше RSIZE_MAX
  • count больше destsz (произошло бы переполнение буфера)
  • исходный и целевой объекты перекрываются
Поведение не определено, если размер символьного массива, на который указывает dest < count <= destsz; другими словами, ошибочное значение destsz не позволяет обнаружить надвигающееся переполнение буфера.
Как и все функции с проверкой границ, memcpy_s гарантированно доступна только в том случае, если реализация определяет __STDC_LIB_EXT1__, а пользователь определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1 до включения <string.h>.

Параметры

dest - указатель на объект, в который выполняется копирование
destsz - максимальное количество байтов, которые можно изменить в целевом объекте (обычно размер целевого объекта)
src - указатель на объект, из которого выполняется копирование
count - количество байтов для копирования

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

1) Возвращает копию dest
2) В случае успеха возвращает ноль, а в случае ошибки — ненулевое значение. Кроме того, при ошибке, если dest не является нулевым указателем и destsz является допустимым, записывает destsz нулевых байтов в целевой массив.

Примечания

memcpy можно использовать для установки эффективного типа объекта, полученного с помощью функции выделения памяти.

memcpy — самая быстрая библиотечная функция для копирования памяти. Обычно она эффективнее, чем strcpy, которой необходимо просматривать копируемые данные, или memmove, которой необходимо принимать меры для обработки перекрывающихся областей.

Некоторые компиляторы C преобразуют подходящие циклы копирования памяти в вызовы memcpy.

Если строгое правило алиасинга запрещает рассматривать одну и ту же область памяти как значения двух разных типов, для преобразования значений можно использовать memcpy.

Пример

#define __STDC_WANT_LIB_EXT1__ 1
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    // simple usage
    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]);

    // 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};
    memcpy(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;
    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 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
}

Возможный вывод:

once
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.1 Функция memcpy (стр. TBD)
    • K.3.7.1.1 Функция memcpy_s (стр. TBD)
  • Стандарт C17 (ISO/IEC 9899:2018):
    • 7.24.2.1 Функция memcpy (стр. TBD)
    • K.3.7.1.1 Функция memcpy_s (стр. TBD)
  • Стандарт C11 (ISO/IEC 9899:2011):
    • 7.24.2.1 Функция memcpy (стр. 362)
    • K.3.7.1.1 Функция memcpy_s (стр. 614)
  • Стандарт C99 (ISO/IEC 9899:1999):
    • 7.21.2.1 Функция memcpy (стр. 325)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
    • 4.11.2.1 Функция memcpy

См. также

memccpy
(C23)
копирует один буфер в другой, останавливаясь после указанного разделителя
(функция)
memmovememmove_s
(C11)
перемещает данные из одного буфера в другой
(функция)
wmemcpywmemcpy_s
(C95)(C11)
копирует заданное количество широких символов между двумя неперекрывающимися массивами
(функция)
Документация C++ для memcpy

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/string/byte/memcpy

Spec-Zone.ru

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