IT Academy
Справочник курса

Язык C и системное программирование

Все объяснения, задачи и лабораторная в одном месте.

Можно сохранить страницу в PDF через печать браузера. Для печати разборы ответов раскрываются автоматически.

1. Компиляция, типы и модель памяти C

Объяснение

Компиляция проверяет типы и создаёт объектные файлы; линкер разрешает внешние символы. У объекта есть размер, выравнивание и время жизни. Чтение неинициализированных значений и выход за границы могут приводить к undefined behavior.

Задача для самостоятельного решения

Чем отличается ошибка синтаксиса от undefined reference?

Показать разбор ответа

Синтаксис отвергается компилятором. Undefined reference обычно означает, что линкер не нашёл реализацию объявленной функции: проверьте исходники, библиотеки и порядок линковки.

2. Указатели, массивы и строки

Объяснение

Указатель хранит адрес объекта, но сам по себе не хранит длину массива. Строка C заканчивается нулевым байтом. Для N символов требуется N+1 байт, если используется терминатор.

Задача для самостоятельного решения

Сколько байтов нужно для строки hello и почему sizeof указателя не даёт длину?

Показать разбор ответа

Нужно 6 байтов. sizeof указателя сообщает размер адреса в данной ABI, а strlen считает символы до нуля; вызывать strlen для массива без терминатора нельзя.

3. Структуры, layout и владение ресурсами

Объяснение

Структура может содержать padding для выравнивания полей. Копирование структуры с указателями не копирует выделенные данные. Владение ресурсом означает обязанность освободить его ровно один раз.

Задача для самостоятельного решения

Почему два вызова free после поверхностной копии структуры опасны?

Показать разбор ответа

Оба указателя ведут к одному блоку. Первый free завершает время жизни, второй вызывает double free. Либо выполняйте глубокую копию, либо явно передавайте владение.

4. Динамическая память и sanitizers

Объяснение

malloc может вернуть NULL; realloc при неудаче оставляет старый блок действительным. Sanitizers обнаруживают многие ошибки памяти в выполненных путях, но не доказывают отсутствие всех дефектов.

Задача для самостоятельного решения

Почему p=realloc(p,n) может потерять память при неудаче?

Показать разбор ответа

NULL перезапишет единственную ссылку на старый блок. Сначала сохраните результат во временный указатель и заменяйте p только после проверки успеха.

5. Файлы, сокеты и системные вызовы

Объяснение

read и write могут обработать меньше байтов, чем запрошено. Сокет — поток байтов, а не поток сообщений. Протоколу нужны длина, разделитель или другая схема определения границ.

Задача для самостоятельного решения

Клиент отправил 100 байтов, read вернул 40. Это ошибка?

Показать разбор ответа

Не обязательно. Нужно продолжить чтение до требуемой длины, EOF или ошибки. Один write отправителя не соответствует одному read получателя.

6. Сборка Make/CMake, тесты и профилирование

Объяснение

Сборка описывает зависимости артефактов. Предупреждения компилятора помогают обнаружить неверные преобразования и недостающие объявления. Бенчмарк без оптимизаций измеряет иную программу, чем production binary.

Задача для самостоятельного решения

Какие сборки нужны для учебного CLI?

Показать разбор ответа

Отладочная с символами и sanitizers для корректности; оптимизированная для измерений. Проверяйте одинаковые входы и результат, иначе ускорение может быть следствием пропущенной работы.

Практика

Лабораторная работа

Подготовка

C-компилятор. Сохраните как main.c; соберите cc -Wall -Wextra -g -fsanitize=address,undefined main.c -o lab.

Учебный пример

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    size_t n = 4;
    int *values = calloc(n, sizeof *values);
    if (!values) return 1;
    for (size_t i=0; i<n; ++i) values[i] = (int)i;
    printf("%d\n", values[3]);
    free(values);
    return 0;
}

Как работает пример и что ожидать

Программа печатает 3. Проверка calloc предотвращает разыменование NULL, цикл не выходит за границу n, free завершает владение. Sanitizers помогают в тестовом запуске, но не заменяют анализ всех путей ошибок.

Итоговая работа

Сделайте CLI, читающий строки из файла с лимитом длины. Обработайте пустой файл, ошибку открытия, длинную строку и ошибку выделения. Затем добавьте socket client с циклом частичных чтений и явным протоколом длины.

Проверка результата

1. Опишите исходные данные и условия запуска, чтобы другой человек мог повторить работу.
2. Приложите результат обычного сценария и сравните его с ожидаемым.
3. Проверьте неверный вход, граничный случай и отказ зависимости, если она есть.
4. Объясните выбранное решение и известное ограничение.
5. Сохраните исправления после самопроверки вместе с примером, который раньше не работал.

Как оценить работу

По каждому пункту поставьте 0 (не выполнено), 1 (выполнено с пробелами) или 2 (результат воспроизводим и объяснён). Если обязательный сценарий не работает, вернитесь к нему независимо от общей суммы. Это рубрика самопроверки: сайт не исполняет присланный код и не выдаёт автоматическую оценку проекта.