Memcpy

Правильный заголовок этой статьи — memcpy. Он показан некорректно из-за технических ограничений.

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

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

Содержание

Определение

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(), принуждая работать правильно даже неправильно написанную программу, однако при написании переносимой программы на это надеяться нельзя.

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

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));

Источники

Ссылки

См. также

  • memmove
  • strcpy
  • memset
  • Стандартная библиотека Си
  • ANSI C
  • POSIX
  • libc
 
Начальная страница  » 
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 Home