2016-07-06 3 views
0

Я смотрю на какой-то код и думаю, что вся логика здесь не имеет смысла. Кажется довольно бедным, чтобы иметь такой макрос. В качестве примера я использую этот макрос дважды, и я получаю обе строки для вывода.Статические переменные внутри макросов

TESTING("hello"); 
TESTING("world"); 
  1. Препроцессор просто заменяет идентификатор с блоком кода, это то же самое, как копировать/вставить код, поэтому не должен компилятор дать ошибку переопределения для FirstPass, при использовании этого макроса много раз? (Если вы вручную вставить в main, static bool firstPass = true; несколько раз, компилятор выдаст сообщение об ошибке.)

  2. Если firstPass является static, он создается и инициализируется только один раз. Таким образом, использование этого макроса несколько раз не должно давать никаких результатов (кроме первого использования), поскольку флаг был установлен в false, но он все равно делает cout каждый раз.

Немного смущенный.

#define TESTING(input)       \ 
{            \ 
    static bool firstPass = true;     \ 
    if (firstPass) {        \ 
    std::cout << input;       \ 
    firstPass = false;       \ 
    }            \ 
} 
+4

Да, плохо использовать макросы вместо шаблонов функций. – LogicStuff

+3

Этот код бессмыслен. Каждый раз, когда вы его вызываете, у вас будет новый 'firstPass' из-за правил определения области. – NathanOliver

+1

Ваше недоразумение похоже на макросодержание (в частности, блок, '{...}'), а не сам макрос. То есть, если вы вручную копируете и вставляете содержимое макроса, как вы говорите, у вас есть такая же проблема без участия каких-либо макросов. – chris

ответ

4

Этот макрос не может работать должным образом. Ключ к тому, почему компилятор разрешает это { }, окружающий static bool firstPass. Это создает новую область, которая позволяет новой переменной скрыть любую другую переменную этим именем. Когда эта область заканчивается, статичность больше не видна.

Из-за новых областей, это законно:

void f() 
{ 
    int i = 0; 
    { 
     int i = 1; 
     { 
      int i = 2; 
     } 
    } 
} 

Это будет работать так, как это было задумано, перемещая FirstPass из макроса.

static bool firstPass = true; 
#define TESTING(input)       \ 
{            \ 
    if (firstPass) {        \ 
    std::cout << input;       \ 
    firstPass = false;       \ 
    }            \ 
} 

ETA: Или, может быть, это действительно работает, как предполагалось. Когда статический bool внутри макроса, каждый сайт вызова будет печатать свой вывод ровно один раз, потому что каждый сайт вызова имеет свой собственный экземпляр флага firstPass. При статическом bool вне макроса только первый доступный сайт вызова будет сообщать о его выходе и только в первый раз, когда он будет достигнут.

Так со статической BOOL внутри макроса,

f() 
{ 
    for (int i = 0; i < 1000; ++i) 
    { 
     TESTING("A\n"); 
     TESTING("B\n"); 
     TESTING("C\n"); 
    } 
} 

int main() 
{ 
    for (int i = 0; i < 5; ++i) 
     f(); 
    return 0; 
} 

напечатает

A 
B 
C 

но со статическим BOOL вне макроса, он будет печатать только

A 
+0

Смешные; Я бы сказал, что он работает точно так, как предполагалось. При первом вызове каждого вызова 'TESTING' он сообщает, что он запускается, а не после этого. Но тогда вопрос становится «каково намеренное поведение». Мы оба правильны (для наших предположений о том, что предназначено); это просто разные интерпретации или предположения о том, что предназначено. –

+0

Ahhhh, я не думал, что намерение состоит в том, чтобы сообщать только в первый раз через какой-либо конкретный сайт вызова. –

Смежные вопросы