
ЛАБОРАТОРНАЯ РАБОТА 1 (IF_COMP)
Директивы препроцессора
Препроцессор - особая программа, которая обрабатывает текст с исходным модулем программы до компилятора и заменяет символические аббревиатуры в программе на соответствующие директивы, включает тексты других файлов в текст вашей программы, изменяет условия компиляции.
Директивы препроцессора начинаются с символа # в первой позиции строки ( для некоторых версий языка это необязательно). Директивы могут быть продолжены на другую строку, если в конце продолжаемой строки поставить символ \ . Точка с запятой в конце директивы не ставится.
Определяющие директивы Символические константы
Директива #define (макроопределение) может появиться в любом месте программы , и ее действие распространяется от начала определения до конца файла.
Пример 1.
#define PI 3.1415
#define PI_2 PI/2
#define PX printf("x равен %d \n",x)
#define FLAG
В имени макроопределения не должно быть пробелов и оно обычно пишется большими буквами.Строка замещения может отсутствовать - символическая константа будет определена, но не имеет значения.
Если препроцессор находит в программе имя макроопределения, он заменяет его на строку замещения (кроме тех случаев, когда имя макроопределения находится в символьной или строковой константе). Если препроцессор встретил макроопределение в строке замещения, он тоже делает подстановку.
Пример 2.
/* текст программы до обработки препроцессором */ #include<stdio.h>
#define PI 3.1415
#define PI_2 PI/2
#define PX printf("x равен %f\n",x)
void main(void)
{
float r=4,x;
x=PI_2*r*r;
PX;
printf("PI равно %f\n",PI);
}
/* текст программы после обработки препроцессором */ /* содержимое файла stdio.h */
Void main(void)
{
float r=4,x;
x=3.1415/2*r*r;
printf("x равен %f\n",x);
printf("PI равно %f\n",3.1415);
}
Важно, чтобы после всех подстановок не возникли синтаксические и логические ошибки.
Макрофункции
Иногда бывает полезно создать макроопределение с аргументами - макрофункцию. Макрофункция применяется там, где требуется произвести не очень сложные вычисления, и хороши тем, что они выполняются для любых типов данных (в отличие от обычных функций).
Однако, следует быть очень внимательным с использованием аргументов, поскольку происходит всего лишь подстановка аргумента
в строку замещения, после которой, возможно, появятся синтаксические и логические ошибки (связанные с приоритетами операций).
Пример 3.
/* текст программы до обработки препроцессором */ #include<stdio.h>
#define SQUARE(x) x*x
Void main(void)
{
int y=5,rez;
printf("квадрат y равен %d\n",SQUARE(y)); printf("квадрат y+2 равен %d\n",SQUARE(y+2)); printf("частное равно %f\n",100./SQUARE(y));
}
После выполнения программы получен результат: квадрат y равен 25
квадрат y+2 равен 17
частное равно 100.000000
/* текст программы после обработки препроцессором */ /*содержимое файла stdio.h */
Void main(void)
{
int y=5,rez;
printf("квадрат y равен %d\n",y*y); printf("квадрат y+2 равен %d\n",y+2*y+2); printf("частное равно %f\n",100./y*y);
}
После подстановки порядок выполнения операций не тот, который мы предполагали. Чтобы избежать побочных эффектов макро соблюдайте ПРАВИЛО:
каждый аргумент в строке замещения, все выражение в целом, а также, возможно, отдельные части выражения заключать в круглые скобки.
#define SQUARE(x) ((x)*(x))
После такого макроопределения подстановка приведет к ожидаемым результатам.
Предопределенные макроопределения
Некоторые макро являются предопределенными (имя начинается и заканчивается двумя подчеркиванием):__FILE__ , __LINE__ , __DATE__ , __TIME__ ,__TINY__ , __SMALL__ , __MEDIUM__ , __COMPACT__ , __LARGE__,__HUGE__(последние шесть макро определены в зависимости от используемой модели памяти).
Пример 4.
/* некоторые предопределенные макроопределения */ #include<stdio.h>