memcpy (от  — копирование памяти) — функция стандартной библиотеки языка программирования Си, копирующая содержимое одной области памяти в другую.

Функция определена в заголовочном файле string.h (а также в mem.h), описывается в стандартах ANSI C и POSIX.

memcpy_s Чтобы не выполнять лишних действий, функция memcpy() не проверяет соответствие размера выходного буфера количеству копируемых байт, возлагая эту обязанность на программиста. В результате совершается достаточно много ошибок, способных привести к переполнению буфера.

Поэтому ближе к концу 2009 г. компания Microsoft добавила memcpy(), CopyMemory() и RtlCopyMemory() в список функций, запрещённых в соответствии с методикой разработки безопасных программ Secure Development Lifecycle (SDL). Те разработчики, которые хотят создавать совместимые с SDL приложения, должны будут использовать вместо memcpy() функцию memcpy_s, позволяющую указывать размер буфера. Функция memcpy_s() непереносима и не включена в стандарт Си.

Определение void *memcpy(void *dst, const void *src, size_t n); где: dst — адрес буфера назначения srс — адрес источника n — количество байт для копирования

Функция копирует n байт из области памяти, на которую указывает src, в область памяти, на которую указывает dst. Функция возвращает адрес назначения dst.

Области памяти не должны перекрываться , иначе данные могут быть скопированы неправильно, например таким образом: __src___

1234567890xxxxx |__ ___| dst после копирования буфер dst содержит данные отличные от исходных, так как они были разрушены в процессе копирования: __dst___

121212121212xxx Что получится на самом деле, зависит от реализации функции (пример относится к одной из реализации приведённых ниже).

Для правильного копирования перекрывающихся областей нужно использовать функцию memmove(). Некоторые реализации memcpy() (например в libc FreeBSD и OpenBSD) делают то же что и memmove(), принуждая работать правильно даже неправильно написанную программу, однако при написании переносимой программы на это надеяться нельзя.

Алгоритм работы и реализации memcpy() копирует содержимое src в буфер dst, например, так: int i;

for( i = 0; i < n; i++ ) ((unsigned char*)dst)[i] = ((unsigned char*)src)[i];

return dst; Но данный пример будет работать медленнее, чем любые практические реализации, так как они оптимизированы: Не используют индексы, как в примере. Перемещают за один цикл не один байт, а блок, равный машинному слову (2, 4 или 8 байт; 16, 32 или 64 бит), которое копируется процессором за то же время, что и байт. Такой подход наиболее эффективен при копировании данных, выровненных на границу машинного слова. Иногда используют инструкции процессора для работы с блоками данных (movsX для i386) в этом случае функция пишется с применением языка ассемблера

Пример частично оптимизированной версии: int i, m; unsigned long *wdst = dst; // текущая позиция в буфере назначения unsigned long *wsrc = src; // текущая позиция в источнике unsigned char *cdst, *csrc;

for(i = 0, m = n / sizeof(long); i < m; i++) // копируем основную часть блоками по 4 или 8 байт *(wdst++) = *(wsrc++); // (в зависимости от платформы)

cdst = (unsigned char*)wdst; csrc = (unsigned char*)wsrc;

for(i = 0, m = n % sizeof(long); i < m; i++) // остаток копируем побайтно *(cdst++) = *(csrc++);

return dst;

Данная версия копирует 4 или 8 байт (размер типа long равен 32 битам) за цикл, но не проверяет выровненность данных.

Пример использования #include <string.h>

unsigned int array; // источник unsigned char byte_array[sizeof(array) * sizeof(unsigned int)]; // буфер назначения

memcpy(byte_array, array, sizeof(byte_array));

См. также memmove strcpy memset ANSI C POSIX libc

Ссылки Описание функции memcpy() в стандарте POSIX Описание функции memcpy в составе Visual C++ Сравнение скорости работы memcpy и цикла на C Патч в ядре Linux, оптимизирующий memcpy

Категория:String.h