Документация по C
Краткий справочник по C с примерами. Прочитай концепцию, посмотри код, а затем потренируйся в курсе Coddy.
Начало работы
- что такое CC — небольшой, быстрый компилируемый язык 1972 года, на котором до сих пор работают операционные системы, базы данных и почти каждое встраиваемое устройство. Вот что это такое, где он работает и почему его стоит учить в 2026 году.
- установка C (GCC)Установка рабочего компилятора C на любой системе: MinGW-w64 в Windows, clang от Apple в macOS и gcc в Linux — плюс как проверить, что установка удалась, и скомпилировать первый файл.
- компиляция и запускПревращаем файл .c в работающую программу: команда gcc, что на самом деле делают препроцессирование, компиляция и компоновка, флаги, которые стоит использовать с первого дня, и как читать ошибки, когда всё ломается.
- синтаксис CУ любой программы на C один и тот же скелет: подключения заголовков, функция main, инструкции с точкой с запятой и блоки в фигурных скобках. Разбираем, что делает каждая часть и какие правила компилятор действительно требует соблюдать.
- комментарииВ C есть два вида комментариев — однострочные // и многострочные /* */ — с разной историей и одной ловушкой вложенности. Разбираем, как пользоваться обоими, а заодно что стоит комментировать, а что нет.
Переменные и типы
- переменныеКак объявить переменную в C, чем объявление отличается от инициализации, правила именования, объявление нескольких переменных сразу и почему неинициализированная переменная — самый частый баг новичка.
- типы данныхУ каждой переменной в C есть тип, который задаёт её размер и то, что она может хранить. Здесь — все базовые типы, их реальные размеры, знаковые и беззнаковые варианты, sizeof, limits.h и что происходит при переполнении.
- константыТри способа дать имя значению, которое никогда не меняется, — ключевое слово const, макросы #define и константы enum: чем каждый из них на самом деле является и когда какой выбрать.
- операторыВсе операторы C, которые стоит знать, — арифметические, присваивания, сравнения, логические и инкремента, — плюс ловушка целочисленного деления, поведение остатка с отрицательными числами и таблица приоритетов, которой можно доверять.
- логический типДо C99 в C не было логического типа. Ноль — ложь, всё остальное — истина, сравнения возвращают int, а stdbool.h добавляет сверху bool, true и false. Плюс знаменитый баг с = вместо ==, который порождён этой схемой.
- Приведение типовC постоянно преобразует значения между типами — иногда потому, что вы попросили приведением, а чаще сам по себе. Здесь — правила продвижения, синтаксис явного приведения и преобразования, тихо теряющие данные.
Поток управления
- if / elseКак C принимает решения: оператор if, else, цепочки else if, вложенность и тернарный оператор — плюс правило истинности (0 — ложь, всё остальное — истина) и ошибка `=` вместо `==`, которая незаметно ломает условия.
- switchКак оператор switch в C выбирает одну ветку из списка констант: метки case, зачем нужен break, намеренное и случайное проваливание, default, switch по символам и перечислениям и когда switch лучше цепочки else if.
- цикл forКак повторять код с помощью цикла for в C: заголовок из трёх частей, счёт вверх и вниз, обход массивов с приёмом sizeof, вложенные циклы, бесконечные циклы, а также ошибки смещения на единицу и беззнаковых типов.
- цикл whileКак цикл while в C повторяется до изменения условия — правило «сначала условие», циклы со сторожевым значением, чтение ввода до EOF, while(1) и перевод между for и while.
- цикл do-whileЦикл C, который сначала действует, а потом проверяет: как do-while гарантирует один проход до проверки, почему он заканчивается точкой с запятой, для каких меню и повторных запросов он создан и чем отличается от обычного while.
- break и continuebreak выходит из цикла или switch; continue переходит к следующему проходу. Как каждый из них ведёт себя в for, while и do-while, как выбраться из вложенных циклов с помощью флага или goto и какие злоупотребления делают цикл нечитаемым.
Функции
- функцииКак определять и вызывать функции в C — тип возвращаемого значения, параметры, return, функции void, зачем нужна декомпозиция, и полный разобранный пример, собранный из маленьких именованных частей.
- параметры функцийВ C всё передаётся по значению — функции получают копии, а не оригиналы. Что это значит на практике, как указатели имитируют передачу по ссылке, почему массивы ведут себя иначе и как вернуть несколько результатов.
- прототипы функцийПочему C должен увидеть форму функции до её вызова — написание прототипов, исправление ошибки implicit declaration, прототипы в заголовочных файлах и настоящая разница между f(void) и f().
- рекурсияКак функция на C вызывает саму себя - базовый случай, который её останавливает, разобранные факториал и Фибоначчи, почему наивный Фибоначчи катастрофически медленный, что на самом деле такое переполнение стека и когда цикл лучше.
- область видимостиГде переменная в C видна и сколько живёт: блочная область видимости, параметры функций, глобальные переменные файловой области, статические локальные переменные, переживающие вызовы, статические функции, затенение имён и чем опасны глобальные переменные.
Указатели
- указателиУказатель — это переменная, хранящая адрес в памяти. Эта страница строит идею с нуля: операторы & и *, объявление и разыменование указателей, зачем нужны типы указателей и функция swap(), которая показывает, ради чего указатели вообще существуют.
- арифметика указателейПрибавление 1 к указателю не добавляет 1 байт — оно перемещает его к следующему объекту этого типа. Здесь разобраны ptr+1, инкремент и декремент, разность указателей, их сравнение, обход массива указателем и правило «на один за концом».
- указатели и массивыВ C имя массива почти везде превращается в указатель на его первый элемент. Здесь разобрано это превращение, почему arr[i] буквально равно *(arr+i), почему размер массива приходится передавать в функцию отдельно и чем указатель на массив отличается от массива указателей.
- Указатели на функцииУ функций тоже есть адреса, и указатель на функцию хранит такой адрес. Разбираем синтаксис объявления, показываем, как typedef делает его читаемым, и доходим до колбэков, qsort со своим компаратором и таблиц диспетчеризации.
- NULL-указателиNULL — это адрес, который хранит указатель, когда он не указывает ни на что. Здесь: что такое NULL на самом деле, почему его разыменование роняет программу, чем он отличается от 0 и от неинициализированного указателя, и какие защитные приёмы избавляют код от null-багов.
Массивы и строки
- массивыКак объявлять и инициализировать массивы в C, индексировать их с нуля, вычислять длину через sizeof, перебирать элементы и почему чтение за концом массива — это неопределённое поведение, а не сообщение об ошибке.
- многомерные массивыКак объявлять, инициализировать и перебирать двумерные массивы в C, что на самом деле означает построчное размещение в памяти, почему при передаче двумерного массива в функцию обязательно число столбцов, и разбор примера с матрицами.
- СтрокиВ C нет типа «строка»: строка — это массив char, заканчивающийся байтом '\0'. Здесь выстраивается эта модель, а затем разбираются литералы, печать, перебор символов и то, почему строку нельзя скопировать через =.
- Функции для строкПрактический обзор <string.h>: измерение через strlen, копирование через strcpy и strncpy, склейка через strcat, сравнение через strcmp, поиск через strchr и strstr — и как рассчитать размеры буферов, чтобы ничего не переполнилось.
- Преобразование строкПреобразование между текстом и числами в C: почему atoi не умеет сообщать об ошибке, как правильно пользоваться strtol и strtod с endptr и errno, как получить строку из числа через snprintf и приёмы с одиночной цифрой и '0'.
Динамическая память
- динамическая памятьЗачем нужна куча, как malloc выдаёт память, размер которой определяется во время выполнения, идиома p = malloc(n * sizeof *p), проверка на NULL, освобождение ровно один раз и динамический массив от начала до конца.
- calloc и realloccalloc выдаёт обнулённую память и безопасно перемножает размеры; realloc увеличивает блок, который вы уже заполнили. Здесь разбираются оба, идиома с временным указателем, не дающая утечь памяти при неудачном realloc, и случаи, когда calloc лучше связки malloc и memset.
- утечки памятиЧто такое утечка на самом деле, три способа получить её в программе на C, дисциплина владения, которая их предотвращает, и поиск остального с помощью valgrind и -fsanitize=address - с разбором протекающей программы по шагам.
- стек и кучаГде на самом деле живут ваши данные: автоматическая память на стеке, динамическая в куче и статическая как третья область — вместе с классической ошибкой висячего указателя при возврате локальной переменной и правилом выбора.
Структуры, объединения и перечисления
- структурыКак собрать связанные значения в один тип с помощью struct: объявление, доступ к полям через точку, именованные инициализаторы, массивы структур, вложенность и правило копирования при передаче, которое удивляет всех.
- структуры и указателиКак указывать на структуру в C: оператор стрелка, почему (*p).x требует скобок, передача структур по указателю для изменения или чтобы избежать копий, выделение структуры через malloc и узел связного списка.
- typedefКак typedef даёт существующему типу новое имя: идиома typedef struct с тегом и без, typedef для указателей на функции и массивов и единственный случай, когда typedef вредит, — когда он прячет указатель.
- объединенияКак union в C хранит несколько типов в одних и тех же байтах — почему его размер равен наибольшему члену, почему читать нужно тот член, который вы записали последним, и как размеченное объединение (enum плюс union) делает это безопасным.
- перечисленияКак объявить enum в C: автоматическая нумерация, явные значения, использование перечислений в switch, чтобы компилятор ловил пропущенные case, перевод enum в строку и соглашения об именовании, которые делают код читаемым.
Ввод и вывод
- printfКак на самом деле работает printf в C - модель строки формата, спецификаторы на каждый день, ширина и точность для выровненных столбцов, разумный вывод дробных чисел, возвращаемое значение и почему printf(user_input) - дыра в безопасности.
- scanfКак читать ввод с помощью scanf в C: зачем нужен &, как обрабатываются пробелы, переполнение буфера в %s и ограничение ширины, проверка возвращаемого значения, баг с оставшимся переводом строки и fgets как надёжная альтернатива.
- спецификаторы форматаВсе спецификаторы формата C в одном месте: что означают %d, %s, %c, %f, %p и остальные, модификаторы длины l, ll, h и z, ширина, точность и флаги, а также чем printf отличается от scanf.
- работа с файламиКак читать и записывать файлы в C: таблица режимов fopen, проверка на NULL, запись через fprintf и fputc, чтение через fgets, fscanf и fgetc, канонический построчный цикл и когда нужен бинарный режим.
- аргументы командной строкиКак программа на C читает свою командную строку: устройство argc и argv, перебор аргументов, что лежит в argv[0], преобразование чисел через strtol вместо atoi и маленький калькулятор, который собирает всё воедино.
Препроцессор
- препроцессорПрепроцессор правит текст исходника ещё до того, как его увидит компилятор: вставляет заголовки, подставляет макросы и включает или выключает куски кода. Здесь — всё семейство директив и способ посмотреть на результат его работы.
- макросыОбъектные и функциональные макросы через #define - почему каждому аргументу и всему телу нужны скобки, ловушка многократного вычисления, многострочные макросы с do-while(0) и когда функция или const подходят лучше.
- заголовочные файлыКак разбить программу на C по файлам: что относится к .h, что к .c, стражи включения против двойного подключения, компиляция нескольких файлов вместе и разделяемые глобальные переменные через extern.
- условная компиляцияКак собирать разный код для разных сборок с помощью #ifdef, #ifndef, #if, #elif и #else: отладочные переключатели, ветки под платформы, определение макросов из командной строки через -D и отключение кода через #if 0.
Стандартная библиотека
- математические функцииОбзор math.h - sqrt, pow, fabs, floor и ceil, round, fmod, тригонометрия и логарифмы, INFINITY и NAN - плюс флаг компоновщика -lm, из-за которого возникает классическая ошибка undefined reference.
- случайные числаКак генерировать случайные числа в C с помощью rand() и RAND_MAX, почему srand(time(NULL)) вызывают ровно один раз, отображение в диапазон через % и небольшое смещение, которое оно вносит, случайные дробные числа и воспроизводимые последовательности.
- стандартная библиотекаЧто даёт каждый стандартный заголовок — stdio.h, stdlib.h, string.h, math.h, time.h, ctype.h, limits.h, stdbool.h, stdint.h и assert.h — с коротким рабочим примером на каждый.
Ошибки и отладка
- ошибка сегментацииSegfault означает, что программа обратилась к памяти, которая ей не принадлежит. Здесь пять причин, на которые приходится почти все такие падения, каждая с минимальным примером и исправлением, а также способы найти точную строку с помощью gdb и AddressSanitizer.
- частые ошибкиОшибки, которые хотя бы раз делает каждый программист на C: пропущенная точка с запятой, = вместо ==, неявное объявление функции, scanf без &, сравнение строк через ==, целочисленное деление, неинициализированные переменные и смещение на единицу — каждая как симптом, причина и решение.
- неопределённое поведениеНеопределённое поведение — это код, на который стандарт C не накладывает никаких требований, так что произойти может что угодно, вплоть до удаления оптимизатором ваших проверок. Здесь: что его вызывает, почему «у меня работает» ничего не доказывает и какие флаги его ловят.