Объявление макроса начинается со знака решетки # и ключевого слова define В простейшем макросе заменяется имя на значение
#define AR_SIZE 10 // AR_SIZE в теле программы будет заменяться на 10
Может использоваться как простейшая функция, Каждую переменную необходимо оборачивать в скобки, иначе могут быть проблемы в составных выражениях.
#include <stdio.h> // printf()
#define MUL1(x, y) (x * y) // Неправильно
#define MUL2(x, y) ((x) * (y)) // Правильно
int main(){
printf("%d \n", MUL1(3 + 3, 10)); // Выводит 33
printf("%d \n", MUL2(3 + 3, 10)); // Выводит 60
}
Использование макросов может быть чревато ошибками. В макросах нет проверки типов значений. Их сложно отлаживать. Вот пример кода с непредсказуемым результатом
#include <stdio.h>
#define ABS(x) ((x) < 0 ? -(x) : (x)) // Возвращает абсолютное число
int main(){
int x = 5;
int result = ABS(x++); // Вызываем макрос
printf("result = %d \n", result); // result = 6
printf("x = %d \n", x); // x = 7
}
Удаляет предыдущее определение макроса директивой #define
#include <stdio.h> //printf()
#define PI 3.14
int main(){
printf("%f \n", PI); // Выведет 3.14000
#undef PI
printf("%f \n", PI); // Ошибка 'PI undeclared'
}
#include <stdio.h> // Включение заголовка из компилятора
#include "func.c" // Включение пользовательского заголовка
Условная компиляция #if, #elif, #else, #endif
#if константное выражение
группа операций
#elif константное выражение // #elif может быть много (на один if)
группа операций
#else // #else может быть только один (на один if)
группа операций
#endif // #endif обязательно завершает #if
#ifndef __IMAGE_H__ // Если не определен макрос __IMAGE_H__ (не включался данный файл директивой #include)
#define __IMAGE_H__ // Определяем макрос __IMAGE_H__
// код заголовочного файла
#endif
Защита от повторного включения заголовочного файла может быть сделана более современным способом чем ifndef .. define. Большинство компиляторов поддерживают директиву предотвращающую множественное включение одного h файла
#pragma once
Макрос FILE заменяется на название файла в коде которого он вызван.
printf("%s \n", __FILE__); //> ..\test\main.c
Макрос LINE заменяется на номер строки кода файла в котором он вызван. Полезно для логирования или отладки.
printf("%d \n", __LINE__); //> 5
Выводит текущую дату.
printf("%s \n", __DATE__); //> Dec 30 2022
Выводит текущее время.
printf("%s \n", __TIME__); //> 23:03:48
Выводит используемую версию стандарта Си в формате YYYYMM, где YYYY - год выпуска, а MM - месяц выпуска версии стандарта.
printf("%ld \n", __STDC_VERSION__); //> 199901
Выводит версию GNU C.
printf("%s \n", __VERSION__); //> 8.1.0