#define — это препроцессорная директива, которая просто заменяет все вхождения идентификатора на значение до компиляции. Она не создаёт переменных, не знает о типах, не проверяет границы и не уважает область видимости.
const — это квалификатор, который создаёт настоящую переменную, но заблокированную для записи после инициализации. Переменная const имеет тип, область видимости, участвует в отладке и может быть более безопасной. Такие переменные размещаются в сегменте .rodata или на стеке/в оперативной памяти.
#define — для простых скалярных значений, которые нужны на этапе компиляции, особенно если использовать в препроцессорных условиях или размерах массива (#define SIZE 16).const — для значений, которые нужно типобезопасно передавать, дебажить, и при этом безопасно экспортировать (в заголовочных файлах, межмодульно).const.Пример:
#define PI 3.14159 const double G = 9.81; int arr[PI]; // ОШИБКА! PI не integer int arr2[G]; // ОШИБКА! G не значение времени компиляции
Вопрос: Работает ли const int a = 10; как константа времени компиляции для создания массива: int arr[a];?
Ответ: Нет. В языке C const — это квалификатор, но переменная создаётся и инициализируется во время выполнения, а не во время компиляции, поэтому размер массива должен быть литералом или выражением, известным компилятору. Используйте #define, либо enum { SIZE = 10 };.
Пример ошибки:
const int a = 5; int arr[a]; // В C89/90 не сработает (VLAs появились в C99, но не везде)
История
В медиа-сервере попытались использовать
const intдля задания размеров буфера, думая, что это "константа времени компиляции". На одном компиляторе (GCC, C99) всё работало, но на большинстве — ошибка компиляции (VLA не поддерживаются), срочно переписали на #define.
История
В платформо-зависимом коде определяли строку через
#define NAME "MyApp", использовали в нескольких местах и забыли заключить в скобки. После добавления к строке символов без явных скобок получали неправильные результаты, приводящие к странным багам в логах.
История
На проекте с несколькими модулями определили константу через #define в двух местах с разными значениями (копипаст). Результат — модули работали с разными константами, нонификации данных, которые исправили только при скрупулёзной отладке.