Команды препроцессора
Тут описать цепочку препроцессор - компилятор - линкер. Команды препроцессора начинаются со знака #Команда препроцессора #define
Поиск и замена.#define N 1000
#include <stdio.h> #define N 10 int main() { int i, a[N]; // после работы препроцессора заменится на int i, a[10]; for(i=0; i<N; i++) // это for(i=0; i<10; i++) scanf("%d", &a[i]); for(i=0; i<N; i++) // это for(i=0; i<10; i++) printf("%d ", a[i]); for(i=0; i<N; i++) // это for(i=0; i<10; i++) printf("%d ", a[i]); printf("\n"); return 0; }

#include <stdio.h> // поставим в конце макроса ; #define N 10 ; int main() { int i, a[N]; // после работы препроцессора заменится на int i, a[10;]; ОШИБКА! for(i=0; i<N; i++) // это for(i=0; i<10; ; i++) ОШИБКА scanf("%d", &a[i]); // еще код return 0; }
Добавим аргументы
Хотим написать функцию, которая считает минимум из 2 чисел.Какой тип аргументов и возвращаемого значения должен быть у этой функции? int min(int x, int y); сравнит только целые числа и не сравнит дробные, long long переменные тоже не сравнит. Надо будет написать много функций - для сравнения каждого типа (можем упростить задачу и написать для long long и double, но получим много дополнительного кода при вызове).
#include <stdio.h> int min(int x, int y) { if (x<y) return x; else return y; } // или с помощью оператора ? : int min1(int x, int y) { return (x<y) ? x : y; } int main() { printf("%d\n", min(3, 5)); // 3 printf("%d\n", min(3, -5)); // -5 printf("%d\n", min(5, 5)); // 5 return 0; }
#include <stdio.h> #define min(x,y) x < y ? x : y int main() { printf("%d\n", min(3, 5)); // 3 printf("%d\n", min(3, -5.5)); // -5.5 printf("%d\n", min(5.1, 5.2)); // 5.1 return 0; }

Добавьте скобки
Чему равно значение выраженияmin(3, 5)+2
3<5 : 3 ? 5 + 2
#define min(x,y) (x < y ? x : y)
Больше скобок
Напишем макрос, считающий квадрат числа.#define kvadrat(x) (x*x)
kvadrat(3+2)
(3+2*3+2)
#define kvadrat(x) ((x)*(x))
Как нельзя использовать макросы (когда скобки не помогают)
Макрос нужно не только хорошо написать, но и правильно вызвать. Используем макрос kvadrat. Что будет напечатано?int x = 2; int y = kvadrat(x++); printf("y=%d x=%d\n", y, x);
Чем отличается макрос от функции?
- в функции есть типы аргументов и тип возвращаемого значения;
- макрос - это замена одного текста программы на другой текст программы, операторы этого текста выполняются один за другим; функция - это передача управления в функцию и возврат из нее + передача параметров.
- кто быстрее?
- время компиляции и время исполнения кода.
- не все выражения безопасно указывать в виде аргументов макроса.
#define <stdio.h> int isdigitF (int x) { return '0'<= x && x <= '9'; } int main() { int c; while(isdigitF(c=getchar())) putchar(c); return 0; }
#define <stdio.h> #define isdigitM ('0'<= (x) && (x) <= '9') int main() { int c; while(isdigitM(c=getchar())) putchar(c); return 0; }
int main() { int c; while(('0'<= (c=getchar()) && (c=getchar()) <= '9')) putchar(c); return 0; }
__LINE__, __FUNCTION__, __FILE__ и другие
макрос | значение |
---|---|
__LINE__ | номер строки в файле |
__FUNCTION__ | имя функции, внутри которой написан __FUNCTION__ |
__FILE__ | имя файла, в котором написан этот макрос |
__TIME__ | время компиляции файла |
#include <stdio.h> #define prn (fprintf(stderr, "%d : %s\n", __LINE__, __FUNCTION__)) int main() { int i; prn; for(i = 0; i < 5; i++); { prn; printf("i=%d\n", i); } prn; return 0; }
1 2 3 4 5 6 7 8 9 10печатается
9 : main 12 : main i=0 12 : main i=1 12 : main i=2 12 : main i=3 12 : main i=4 15 : main