Директива #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.