memcpy и memset
Функции работы с необработанной памятью
«memcpy и memset» — бесплатный урок C Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Функции для работы с необработанной памятью
В отличие от строковых функций, memcpy и memset работают с необработанными байтами и игнорируют нулевые терминаторы.
Они объявлены в <string.h> и работают с указанным Вами количеством байт, поэтому подходят для данных любого типа.
#include <stdio.h>
#include <string.h>
int main(void) {
int src[] = {1, 2, 3};
int dest[3];
memcpy(dest, src, sizeof(src));
printf("%d %d %d\n", dest[0], dest[1], dest[2]);
return 0;
}Сигнатура memcpy
void *memcpy(void *dest, const void *src, size_t n);
Функция копирует ровно n байт из src в dest и возвращает dest. Используйте sizeof, чтобы получить правильное количество байт.
#include <stdio.h>
#include <string.h>
int main(void) {
char src[] = "copy me";
char dest[16];
memcpy(dest, src, strlen(src) + 1);
printf("%s\n", dest);
return 0;
}Правильный подсчёт байт
Количество указывается в байтах, а не в элементах. Для массива int необходимо умножить число элементов на sizeof(int).
Применение sizeof(array) к настоящему массиву автоматически даёт его общий размер в байтах.
#include <stdio.h>
#include <string.h>
int main(void) {
double a[4] = {1.5, 2.5, 3.5, 4.5};
double b[4];
memcpy(b, a, 4 * sizeof(double));
printf("%.1f %.1f\n", b[0], b[3]);
return 0;
}Области не должны перекрываться
memcpy приводит к неопределённому поведению, если области источника и назначения перекрываются.
Если диапазоны могут перекрываться (например, при сдвиге элементов внутри одного массива), используйте memmove, которая безопасно обрабатывает перекрытия.
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[] = "ABCDEF";
memmove(buf + 2, buf, 4);
printf("%s\n", buf);
return 0;
}Сигнатура memset
void *memset(void *ptr, int value, size_t n);
Функция заполняет n байт по адресу ptr байтовым значением value. Значение интерпретируется как unsigned char, поэтому имеют значение только младшие 8 бит.
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[6];
memset(buf, 'x', 5);
buf[5] = '\0';
printf("%s\n", buf);
return 0;
}Обнуление памяти
Чаще всего memset используют для очистки буфера или структуры, устанавливая все байты в ноль перед использованием.
memset(arr, 0, sizeof(arr)) устанавливает каждый байт в 0, что является допустимым нулевым представлением для целых чисел, чисел с плавающей точкой и указателей.
#include <stdio.h>
#include <string.h>
int main(void) {
int counts[5];
memset(counts, 0, sizeof(counts));
for (int i = 0; i < 5; i++) printf("%d ", counts[i]);
printf("\n");
return 0;
}memset работает побайтно
Будьте осторожны: memset устанавливает каждый байт, а не каждый элемент. Если с её помощью заполнить массив int значением 1, единицы не получатся.
Каждый элемент типа int получит во всех байтах значение 0x01, то есть 0x01010101, а не 1.
#include <stdio.h>
#include <string.h>
int main(void) {
int a[2];
memset(a, 1, sizeof(a));
printf("%d\n", a[0]);
return 0;
}Очистка структуры
memset удобно использовать, чтобы одним вызовом инициализировать всю структуру нулями вместо ручной установки каждого поля.
#include <stdio.h>
#include <string.h>
struct Point { int x; int y; int z; };
int main(void) {
struct Point p;
memset(&p, 0, sizeof(p));
printf("%d %d %d\n", p.x, p.y, p.z);
return 0;
}Копирование структур
Структуру можно скопировать с помощью memcpy, хотя обычное присваивание (b = a;) обычно делает то же самое понятнее.
memcpy предпочтительнее при копировании через обобщённые указатели void *, когда типы стёрты.
#include <stdio.h>
#include <string.h>
struct Rec { int id; char tag; };
int main(void) {
struct Rec a = {42, 'A'};
struct Rec b;
memcpy(&b, &a, sizeof(a));
printf("%d %c\n", b.id, b.tag);
return 0;
}memcmp: сравнение памяти
Связанная функция memcmp(a, b, n) сравнивает n необработанных байт и возвращает 0, если они совпадают.
В отличие от strcmp, она не останавливается на нулевом терминаторе, поэтому работает с любыми двоичными данными.
#include <stdio.h>
#include <string.h>
int main(void) {
int a[] = {1, 2, 3};
int b[] = {1, 2, 3};
if (memcmp(a, b, sizeof(a)) == 0)
printf("Arrays have identical bytes\n");
return 0;
}Почему эти функции быстрые
memcpy и memset часто вручную оптимизируют на языке ассемблера, чтобы перемещать много байт за одну инструкцию.
Обычно они намного быстрее цикла побайтной обработки, написанного вручную, поэтому для перемещения и инициализации больших объёмов данных предпочитайте их.
#include <stdio.h>
#include <string.h>
int main(void) {
char big[1000];
memset(big, 0, sizeof(big));
printf("Cleared %lu bytes\n", sizeof(big));
return 0;
}Быстрая проверка
Проверьте, насколько хорошо Вы понимаете побайтовую работу memset.
Итоги
Вы изучили функции для работы с необработанной памятью:
- memcpy копирует n байт; области не должны перекрываться (если перекрытие возможно, используйте memmove).
- memset заполняет n байт одним байтовым значением; особенно удобна для обнуления.
- Размеры указываются в байтах — используйте
sizeofи помните о различии между байтами и элементами. - memcmp сравнивает необработанные байты, не останавливаясь на
'\0'.
Часто задаваемые вопросы
Урок «memcpy и memset» бесплатный?
Да — полный текст урока «memcpy и memset» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «memcpy и memset»?
Функции работы с необработанной памятью Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «memcpy и memset»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.