Memcpy
Материал из Википедии — свободной энциклопедии
- Правильный заголовок этой статьи — memcpy. Он показан некорректно из-за технических ограничений.
memcpy (от англ. memory copy — копирование памяти) — функция стандартной библиотеки языка программирования Cи, копирующая содержимое одной области памяти в другую.
Функция определена в заголовочном файле string.h, описывается в стандартах ANSI C и POSIX.
Содержание |
[править] Определение
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; // текущая позиция в источнике 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));
[править] Источники
[править] Ссылки
- Патч в ядре Linux, оптимизирующий memcpy
- Описание функции memcpy в libc в Linux
- Описание функции memcpy в составе Visual C++
- Сравнение скорости работы memcpy и цикла на C