Язык программирования C++ от Страуструпа


Макросредства - часть 2


Допустимы такие макроопределения:

#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<class T>

inline T min(T a, T b) { return (a<b)?a:b; }




Содержание  Назад  Вперед