Фэндом

Наука

Memcpy

22 248статей на
этой вики
Добавить новую страницу
Обсуждение0 Поделиться

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

Определение Править

void *memcpy(void *dst, const void *src, size_t n);, где:

  • dst — адрес буфера назначения
  • srс — адрес источника
  • n — количество байт для копирования

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

Области памяти не должны перекрываться (\|src-dst\|\ge n), иначе данные могут быть скопированы неправильно, например таким образом:

 __src___
|        |
1234567890xxxxx
  |__dst___|

после копирования буфер dst содержит данные отличные от исходных, т.к. они были разрушены в процессе копирования:

   __dst___
  |        |
121212121212xxx

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

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

Функция определена в заголовочном файле string.h.

Алгоритм работы и реализации Править

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;  // текущая позиция в источнике

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

for(i = 0, m = n - m; i < m; i++)             // остаток копируем побайтно
   *(((unsigned char*)wdst)++) = *(((unsigned char*)wsrc)++);

return dst;

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

Пример использования Править

#include <string.h>

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

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

Источники Править

  • Описание функции memcpy() в стандарте POSIX [1]

Ссылки Править

  • Патч в ядре Linux, оптимизирующий memcpy [2]
  • Описание функции memcpy в libc в Linux [3]
  • Описание функции memcpy в составе Visual C++ [4]
  • Сравнение скорости работы memcpy и цикла на C [5]

См также Править

Обнаружено использование расширения AdBlock.


Викия — это свободный ресурс, который существует и развивается за счёт рекламы. Для блокирующих рекламу пользователей мы предоставляем модифицированную версию сайта.

Викия не будет доступна для последующих модификаций. Если вы желаете продолжать работать со страницей, то, пожалуйста, отключите расширение для блокировки рекламы.

Также на Фэндоме

Случайная вики