Явная память
Выделение и освобождение динамической памяти выполняется через
malloc, calloc, realloc
и free.
Раздел справочника
C — компактный компилируемый язык системного программирования, который даёт прямой контроль над памятью, представлением данных, указателями, ABI и взаимодействием с операционной системой. Этот раздел содержит краткие справочные материалы по синтаксису, типам, функциям, массивам, структурам, препроцессору и стандартной библиотеке C.
Обзор
C близок к машинной модели: данные имеют конкретное представление в памяти, указатели хранят адреса, а многие операции почти напрямую отображаются в машинный код. Именно поэтому язык широко используется в системном программировании, embedded-разработке, библиотеках, runtime-компонентах, сетевом коде и высокопроизводительных сервисах.
Выделение и освобождение динамической памяти выполняется через
malloc, calloc, realloc
и free.
Функции принимают значения. Для изменения объекта вызывающей стороны обычно передают указатель на этот объект.
Выход за границы массива, use-after-free, разыменование невалидного указателя и signed overflow могут привести к неопределённому поведению.
Language
Целые типы, floating-point, char, bool, enum, typedef, квалификаторы.
УказателиАдреса, разыменование, pointer arithmetic, null pointer, void*.
МассивыСтатические массивы, decay к указателю, многомерные массивы.
ФункцииОбъявления, определения, прототипы, указатели на функции.
Структурыstruct, union, bit-fields, padding, alignment и layout данных.
Препроцессор#include, #define, условная компиляция, include guards.
Types
Тип в C определяет размер объекта, допустимые операции, правила
преобразования и интерпретацию битового представления. Для переносимого
кода важно не полагаться на конкретный размер int,
long или указателя без явной проверки.
char, short, int, long, long longuint8_t, int32_t, uint64_t<stdint.h>, удобны для протоколов и бинарных форматов.float, double, long doublestruct, union, enum, typedef#include <stdint.h>
#include <stddef.h>
struct packet_header {
uint16_t type;
uint16_t flags;
uint32_t payload_size;
};
size_t header_size(void) {
return sizeof(struct packet_header);
}
Memory
Указатель хранит адрес объекта или функции. Через указатели C реализует передачу объектов по ссылке, работу с массивами, динамическую память, буферы, строки, callback-функции и интерфейсы системных API.
Локальные переменные обычно живут до выхода из блока. Возвращать указатель на такую переменную нельзя.
Память, выделенная через malloc, живёт до вызова
free или до завершения процесса.
Глобальные и статические объекты существуют в течение всей работы программы.
Арифметика указателей выполняется в единицах размера типа, на который указывает указатель.
malloc, calloc или
realloc должен иметь понятного владельца и соответствующий
путь освобождения через free.
#include <stdlib.h>
int *make_array(size_t count) {
int *data = malloc(count * sizeof(*data));
if (data == NULL) {
return NULL;
}
for (size_t i = 0; i < count; ++i) {
data[i] = 0;
}
return data;
}
void destroy_array(int *data) {
free(data);
}
Arrays
Массив в C — это непрерывная область элементов одного типа. В большинстве выражений имя массива преобразуется в указатель на первый элемент. Это часто называют array-to-pointer decay.
#include <stddef.h>
int sum_array(const int *values, size_t count) {
int sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += values[i];
}
return sum;
}
Строки в C — это массивы символов, завершающиеся нулевым байтом
'\0'. Большинство функций из <string.h>
ожидают именно такую форму строки.
Data layout
struct объединяет несколько полей в один объект.
Компилятор может добавлять padding между полями для соблюдения
требований выравнивания. Поэтому бинарный layout структуры может
зависеть от платформы, ABI и настроек компилятора.
#include <stdint.h>
struct point {
int32_t x;
int32_t y;
};
struct rectangle {
struct point left_top;
struct point right_bottom;
};
Все поля существуют одновременно. Размер структуры не меньше суммы размеров её полей и может включать padding.
Несколько полей используют одну и ту же область памяти. В каждый момент корректно интерпретируется только активный вариант.
Позволяют описывать поля с заданным количеством бит, но их layout часто зависит от реализации.
Preprocessor
Препроцессор выполняется до компиляции: подключает заголовочные файлы, раскрывает макросы и обрабатывает условную компиляцию. Он работает с токенами, а не с типами C, поэтому макросы требуют осторожности.
Подключение заголовков и организация публичного API модулей.
#defineОбъектные и функциональные макросы, подстановка токенов.
Условная компиляция#if, #ifdef, #ifndef, #elif, #else и #endif.
Include guardsЗащита заголовочных файлов от повторного включения.
#ifndef BUFFER_H
#define BUFFER_H
#include <stddef.h>
struct buffer {
unsigned char *data;
size_t size;
size_t capacity;
};
#endif /* BUFFER_H */
Standard library
Стандартная библиотека C предоставляет функции для работы с памятью, строками, вводом-выводом, математикой, временем, сортировкой, преобразованием чисел и базовой диагностикой ошибок.
Файловый и потоковый ввод-вывод: printf, fprintf, fread, fwrite.
<stdlib.h>malloc, free, exit, atoi, strtol, qsort, bsearch.
<string.h>memcpy, memmove, memset, strlen, strcmp, strchr.
<stdint.h>Целые типы фиксированной ширины: uint32_t, int64_t и другие.
<stddef.h>size_t, ptrdiff_t, NULL, offsetof.
<errno.h>Глобальный код ошибки для многих функций стандартной библиотеки и POSIX.
Standards
Examples
#include <stddef.h>
#include <string.h>
int copy_bytes(
unsigned char *dst,
size_t dst_size,
const unsigned char *src,
size_t src_size
) {
if (dst == NULL || src == NULL) {
return -1;
}
if (src_size > dst_size) {
return -1;
}
memcpy(dst, src, src_size);
return 0;
}
Размер буфера передаётся явно. Функция не делает предположений о длине данных и проверяет границы перед копированием.
#include <stddef.h>
struct stats {
size_t packets;
size_t errors;
};
void stats_add_packet(struct stats *s) {
if (s == NULL) {
return;
}
s->packets += 1;
}
void stats_add_error(struct stats *s) {
if (s == NULL) {
return;
}
s->errors += 1;
}
Если функция должна изменить объект вызывающей стороны, обычно передают указатель на этот объект.