Директива #define определяет идентификатор и последовательность символов, которые будут подставляться вместо идентификатора каждый раз, когда он встретится в исходном файле. Формальное определение директивы:
#define идентификатор последовательность_символов
Определяемый идентификатор еще называют препроцессорным символом. Используем директиву #define:
#include <stdio.h>
#define N 23
int main(void)
{
int x = N;
printf("Number: %d", x); // Number: 23
return 0;
}
Здесь определен один идентификатор N. В программе, где встречается этот идентификатор, он будет заменяться на число 23. Например, строка
int x = N;
после обработки препроцессором будет иметь следующий код
int x =23;
Более сложный пример
#include <stdio.h>
#define BEGIN {
#define END }
#define N 23
int main(void)
BEGIN
int x = N;
printf("Number: %d", x); // Number: 23
return 0;
END
Здесь определены три идентификатора BEGIN, END, N. В итоге все вхождения последовательности символов "BEGIN" будут заменяться на открывающую фигурную скобку, а "END" - на закрывающую, а символ "N" на число 23.
Таким образом, после обработки препроцессора функция main приобретет следующий вид:
int main(void)
{
int x = 23;
printf("Number: %d", x);
return 0;
}
#define также может определять более сложные выражения. Например:
#include <stdio.h>
#define ADD(a,b) (a+b)
int main(void)
{
int n1 = 10;
int n2 = 5;
printf("%d + %d = %d", n1, n2, ADD(n1, n2)); // 10 + 5 = 15
}
В данном случае выражение ADD(a,b) будет заменяться операцией сложения двух чисел (a + b)
Особенно удобно использовать директиву #define для определения размеров массивов:
#include <stdio.h>
#define N 4
int main(void)
{
int numbers[N] = {1, 2, 3, 4};
for(int i=0; i<N; i++)
{
printf("%d ", numbers[i]);
}
return 0;
}
В данном случае если мы захотим глобально поменять размер массива, то достаточно изменить значение N в директиве define.
Следует учитывать, что директива препроцессор не заменяет последовательности символов в двойных и одинарных кавычках и в комментариях:
#include <stdio.h>
#define N 4
int main(void)
{
char symbol = 'N';
printf("%c \n", symbol); // N
printf("N"); //N
return 0;
}
Причем если идентификатор должен представлять одно слово, то его последовательность символов может состоять из нескольких слов или символов, разделенных пробелами:
#define REAL long double
В процессе работы мы можем многократно определять новое значение для одного идентификатора:
#define N 23 #define N 32 #define N 55
Но некоторые компиляторы, в частности, gcc, могут выдавать предупреждения при повторном определении идентификатора, и чтобы выйти из этой ситуации, мы можем использовать директиву #undef для отмены действия макроса. Эта директива имеет следующее определение:
#undef идентификатор
Например:
#include <stdio.h>
#define STRING "Good morning \n"
int main(void)
{
printf(STRING);
#undef STRING
#define STRING "Good afternoon \n"
printf(STRING);
#undef STRING
#define STRING "Good evening \n"
printf(STRING);
return 0;
}
При использовании компилятора GCC мы можем с помощью флага -D определить константу аналогично, как это делается с помощью директивы %define. Для этого применяется выражение
gcc -D ИЛЕНТИФКАТОР=ЗНАЧЕНИЕ
Например, определим следующую программу:
#include <stdio.h>
int main(void)
{
int x = NUMBER;
printf("x = %d\n", x);
return 0;
}
В данном случае переменной x присваивается значение некоторого идентификатора NUMBER. Обратите внимание, что он нигде не определен, и среда разработки или текстовый редактор могут подчеркивать этот идентификатор как некорректный.
Теперь скомпилируем данную программу с помощью следующей команды (допустим, исходный файл называется "app.c"):
gcc -D NUMBER=25 app.c -o app.exe & app.exe
В данном случае мы определяем препроцессорный символ NUMBER и присваиваем ему значение 25. В итоге программа успешно скомпилируется, а переменная x получит значение 25.