0Pricing
C Academy · Урок

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 — локальная установка не требуется.

Все уроки этого курса

  1. strlen, strcpy, strcat
  2. strcmp и сравнение
  3. strtok и разбор на токены
  4. memcpy и memset
← Назад к C Academy