За допомогою #define можна керувати регістровими змінними:
#define REG1 register
#define REG2 register
#define REG3
REG1 int i;
REG2 int j;
REG3 int k;
Тут REG3 компілятор ігнорує.
2. Макроси (макропідстановки)
#define<ідентифікатор1>(<список параметрів>)<текст>
Текст у цьому випадку може містити ідентифікатори, розташовані у списку параметрів. Наприклад:
#define ADD(x,y)((x)+(y));
#define MAX(x,y)((x)>(y))?(x):(y)
…
int i;
i=ADD(5,4)*3//це еквівалентно ((5)+(4))*3
i=ADD(b-3,6)*c//це еквівалентно ((b-3)+(6))*c
Визначимо функцію ADD в описаному вище фрагменті так:
#define ADD(x,y)x+y
У відповідному рядку отримаємо 5 + 4 * 3, тобто за відсутності дужок можна не досягти бажаного результату внаслідок пріоритету операцій. Отже, макропідстановки (макроси) у деякому розумінні є аналогами функцій, але між ними існує суттєва відмінність. Оскільки макроси – це звичайні текстові підстановки, то в місце їх виклику вставляється відповідний текст, тому вони працюють швидше за функції. Адже в точці виклику функції відбувається генерація виклику, засилання формальних параметрів (фактичних), повернення у точку виклику після роботи функції – усі ці дії вимагають часу. Однак використання макросів значно збільшує текст самої програми.
|
|
З використанням директиви #define можна здійснити конкатенацію текстових елементів, тобто утворити нові ідентифікатори. У директиві #define конкатенація здійснюється синтаксично з використанням ##:
#define concat(x,y)x##y
…
concat (x,3)=5;//еквівалентно x3=5
Наприклад:
#define AB'стандарт'
#define A'відхилення від'
#define B'стандарту'
…
char*s=concat(A,B);
printf("s=%s',s);
У цьому фрагменті надрукується "відхилення від стандарту". У макросах спочатку відбувається підстановка замість формальних параметрів їх фактичних значень, а потім виконується послідовність дій, описаних у макросі. Тому надрукується не 'стандарт', а "відхилення від стандарту".
Використання формального параметра, перед яким стоїть значок #<параметр>, приводить до його перетворення на текстовий рядок 'параметр'. Припустимо, що нам необхідно вивести на екран значення деякого параметра макросу у формі "параметр"=<значення>. Наведемо фрагмент програми:
#define write(x)
printf(#x'=%d\n',x)
int a=5,b=3,c=2;
write(a); /*надрукується a=5*/
write(b); /*надрукується b=3*/
write(c); /*надрукується c=2*/
Спочатку конструкція #x перетворюється на текстовий рядок #x->'x', послідовність двох текстових рядків у функції printf сприймається як один:
printf("x"=%d\n',x)
printf("x=%d\n',x)
3.6.2. Директива #undef [<ім’я>]
Директива #undef [<ім ' я>] відмінює дію макровизначення чи макропідстановки, ім'я може бути відсутнім. Така директива не є помилкою у більшості компіляторів. Не вважається помилкою також використання імені, яке раніше не було визначене. У випадку використання макросів параметри можуть бути опущені. Наприклад:
|
|
#define ADD(x,y)(x)+(y)
#define width 80
Main()
{printf ("проба\n');
int i=ADD(5,4);
printf("i=%d\n',i);
#undef ADD
{float i=ADD(3.5,4);
}}
Директива #include
Є два основні типи директиви #include:
#include "шлях"
#include <шлях>
Якщо використовуються подвійні лапки та вказується повний шлях до відповідного файла, то пошук здійснюється за цим шляхом. Якщо шлях указано не повністю, то пошук здійснюється:
a у робочому поточному каталозі, де знаходиться файл відповідної С -програми;
a у каталогах, указаних у командному рядку;
a у стандартних каталогах, що задаються командою pass операційної системи MS-DOS.
Якщо використовуються кутові дужки, то послідовність пошуку відрізняється тим, що ігнорується пошук у робочому каталозі, тобто файл шукається в каталогах, указаних у командному рядку компіляції, та в стандартних. Шлях у цій директиві також може задаватися з використанням макропідстановок:
#define myway "e:\bc\bin\bc\mylib.h'
…
#include myway