Spec-Zone.ru › C

memcpy, memcpy_s

Определено в заголовке <string.h>
(1)
void* memcpy( void *dest, const void *src, size_t count );
(до 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. Оба объекта интерпретируются как массивы unsigned char.
Поведение не определено, если доступ выходит за пределы массива 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 <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.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

Ссылки

  • Стандарт 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/w/c/string/byte/memcpy

Spec-Zone.ru

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