memcpy, memcpy_s
С ru.cppreference.net
| Определён в заголовке <string.h>
|
||
void* memcpy( void* dest, const void* src, size_t count );
|
(1) | (до 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_MAXcountбольше, чемdestsz(произойдёт переполнение буфера)- исходный и целевой объекты перекрываются
Поведение не определено, если размер массива символов, на который указывает
dest < count < = destsz; другими словами, ошибочное значение destsz не раскрывает надвигающееся переполнение буфера. Как и все функции с проверкой границ,
memcpy_s гарантированно доступна только в том случае, если __STDC_LIB_EXT1__ определена реализацией и если пользователь определяет __STDC_WANT_LIB_EXT1__ как целочисленную константу 1 перед включением <string.h>.Параметры
| dest | - | указатель на объект для копирования |
| destsz | - | максимальное количество байт для изменения в целевом объекте (обычно размер целевого объекта) |
| src | - | указатель на объект, из которого производится копирование |
| count | - | количество копируемых байт |
Возвращаемое значение
1) Возвращает копию
dest2) Возвращает ноль при успехе и ненулевое значение при ошибке. Также при ошибке, если
dest не является нулевым указателем и destsz допустим, записывает destsz нулевых байт в целевой массив.Примечания
memcpy может использоваться для установки эффективного типа объекта, полученного с помощью функции выделения памяти.
memcpy является самой быстрой библиотечной процедурой для копирования из памяти в память. Обычно она более эффективна, чем strcpy, которая должна сканировать копируемые данные, или memmove, которая должна принимать меры предосторожности для обработки перекрывающихся входных данных.
Некоторые компиляторы C преобразуют подходящие циклы копирования памяти в вызовы memcpy.
Там, где строгое алиасинг запрещает рассматривать одну и ту же память как значения двух разных типов, memcpy может использоваться для преобразования значений.
Пример
Запустить этот код
#define __STDC_WANT_LIB_EXT1__ 1
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// simple usage
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]);
// setting effective type of allocated memory to be int
int* p = malloc(3 * sizeof(int)); // allocated memory has no effective type
int arr[3] = {1, 2, 3};
memcpy(p, arr, 3 * sizeof(int)); // allocated memory now has an effective type
// reinterpreting data
double d = 0.1;
// int64_t n = *(int64_t*)(&d); // strict aliasing violation
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); // count is greater than 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
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- 7.24.2.1 Функция memcpy (стр.: TBD)
- K.3.7.1.1 Функция memcpy_s (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
- 7.24.2.1 Функция memcpy (стр.: TBD)
- K.3.7.1.1 Функция memcpy_s (стр.: TBD)
- Стандарт 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) |
копирует один буфер в другой, останавливаясь после указанного разделителя (функция) |
(C11) |
перемещает один буфер в другой (функция) |
(C95)(C11) |
копирует определённое количество широких символов между двумя неперекрывающимися массивами (функция) |
Документация C++ для memcpy
| |