Бьерн Страуструп.
Язык программирования С++
119
сложную задачу:
//
ошибка:
#define print(a,b) cout<<(a)<<(b)
#define print(a,b,c) cout<<(a)<<(b)<<(c)
// слишком сложно:
#define fac(n) (n>1) ?n*fac(n-1) :1
Препроцессор работает со строками и практически ничего не знает о синтаксисе C++, типах языка и
областях видимости. Транслятор имеет дело только с уже раскрытым макроопределением, поэтому
ошибка в нем может диагностироваться уже после подстановки, а не при определении макроимени. В
результате появляются довольно путанные сообщения об ошибках.
Допустимы такие макроопределения:
#define
Case break;case
#define forever for(;;)
А вот совершенно излишние макроопределения:
#define PI 3.141593
#define BEGIN {
#define END }
Следующие макроопределения могут привести к ошибкам:
#define SQUARE(a) a*a
#define INCR_xx (xx)++
#define DISP = 4
Чтобы убедиться в этом, достаточно попробовать сделать подстановку в таком примере:
int xx = 0;
// глобальный счетчик
void f() {
int xx = 0;
// локальная переменная
xx = SQUARE(xx+2);
// xx = xx +2*xx+2;
INCR_xx;
// увеличивается локальная переменная xx
if (a-DISP==b) {
// a-=4==b
//
...
}
}
При ссылке на глобальные имена в
макроопределении используйте операцию разрешения области
видимости ($$2.1.1), и всюду, где это возможно, заключайте имя параметра макроопределения в
скобки. Например:
#define MIN(a,b) (((a)<(b))?(a):(b))
Если макроопределение достаточно сложное, и требуется комментарий к нему, то разумнее написать
комментарий вида /* */, поскольку в реализации С++ может использоваться препроцессор С, который
не распознает комментарии вида //. Например:
#define m2(a) something(a) /* глубокомысленный комментарий */
С помощью макросредств можно
создать свой собственный язык, правда, скорее всего, он будет
непонятен другим. Кроме того, препроцессор С предоставляет довольно слабые макросредства. Если
ваша задача нетривиальна, вы, скорее всего, обнаружите, что решить ее с помощью этих средств либо
невозможно, либо чрезвычайно трудно. В качестве альтернативы традиционному использованию
макросредств в язык введены конструкции const, inline и шаблоны типов. Например:
const int answer = 42;
template
inline T min(T a, T b) { return (a
Бьерн Страуструп.
Язык программирования С++
120
Достарыңызбен бөлісу: