Программирование. Принципы и практика использования C++ Исправленное издание, стр. 397
По техническим причинам в языке С (но не в языке C++) неявно допускается, чтобы константы появлялись из других модулей компиляции.
/* файл x.c: */const int x; /* инициализирована в другом месте *//* файл xx.c: */const int x = 7; /* настоящее определение */В языке С++ в разных файлах могут существовать два разных объекта с одним и тем же именем
xconst#define MAX 30void f(int v){ int a1[MAX]; /* OK */ switch (v) { case 1: /* ... */ break; case MAX: /* OK */ /* ... */ break; }}
MAX30a13030MAX27.8. Макросы
• Присваивайте всем макросам имена, состоящие только из прописных букв:
ALL_CAPS• Не присваивайте имена, состоящие только из прописных букв, объектам, которые не являются макросами.
• Никогда не давайте макросам короткие или “изящные” имена, такие как
maxmin• Надейтесь, что остальные программисты следуют этим простым и общеизвестным правилам.
В основном макросы применяются в следующих случаях:
• определение “констант”;
• определение конструкций, напоминающих функции;
• улучшение синтаксиса;
• управление условной компиляцией.
Кроме того, существует большое количество менее известных ситуаций, в которых могут использоваться макросы.
Мы считаем, что макросы используются слишком часто, но в программах на языке С у них нет разумных и полноценных альтернатив. Их даже трудно избежать в программах на языке С++ (особенно, если вам необходимо написать программу, которая должна подходить для очень старых компиляторов или выполняться на платформах с необычными ограничениями).
Мы приносим извинения читателям, считающим, что приемы, которые будут описаны ниже, являются “грязными трюками”, и полагают, что о них лучше не говорить в приличном обществе. Однако мы думаем, что программирование должно учитывать реалии и что эти (очень простые) примеры использования и неправильного использования макросов сэкономят часы страданий для новичков. Незнание макросов не приносит счастья.
27.8.1. Макросы, похожие на функции
Рассмотрим типичный макрос, напоминающий функцию.
#define MAX(x, y) ((x)>=(y)?(x):(y))Мы используем прописные буквы в имени
MAXmaxreturnint aa = MAX(1,2);double dd = MAX(aa++,2);char cc = MAX(dd,aa)+2;Он разворачивается в такой фрагмент программы:
int aa = ((1)>=( 2)?(1):(2));double dd = ((aa++)>=(2)?( aa++):(2));char cc = ((dd)>=(aa)?(dd):(aa))+2;Если бы всех этих скобок не было, то последняя строка выглядела бы следующим образом.
char cc = dd>=aa?dd:aa+2;Иначе говоря, переменная
cc
aa++MAXКакой-то “гений” определил макрос следующим образом и поместил его в широко используемый заголовочный файл. К сожалению, он также назвал его
maxMAXtemplate<class T> inline T max(T a, T b) { return a<b?b:a; }имя
maxT aT btemplate<class T> inline T ((T a)>=(T b)?(T a):(T b))