Namespaces
Variants

memcpy, memcpy_s

From cppreference.net
< c ‎ | string ‎ | byte
Определено в заголовочном файле <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)
{
    // простое использование
    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]);
    // установка эффективного типа выделенной памяти как int
    int *p = malloc(3*sizeof(int));   // выделенная память не имеет эффективного типа
    int arr[3] = {1,2,3};
    memcpy(p,arr,3*sizeof(int));      // выделенная память теперь имеет эффективный тип
    // переинтерпретация данных
    double d = 0.1;
//    int64_t n = *(int64_t*)(&d); // нарушение строгого псевдонимирования
    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);            //  количество больше чем 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

Смотрите также

(C23)
копирует один буфер в другой, останавливаясь после указанного разделителя
(функция)
перемещает один буфер в другой
(функция)
копирует указанное количество широких символов между двумя неперекрывающимися массивами
(функция)