2016-07-06 17 views
0

Ich sehe mir einen Code an und denke, dass die ganze Logik hier keinen Sinn ergibt. Es scheint ziemlich schlecht zu sein, ein solches Makro zu haben. Als Beispiel verwende ich dieses Makro zweimal und ich bekomme beide Zeichenfolgen zur Ausgabe.Statische Variablen innerhalb von Makros

TESTING("hello"); 
TESTING("world"); 
  1. Der Präprozessor einfach den Bezeichner mit dem Codeblock ersetzt, ist es die gleiche wie Kopieren/Einfügen des Code, so sollte nicht der Compiler gibt für Erst-Durchlauf eines Neudefinition Fehler, wenn diesen Makro verwendet mehrmals? (Wenn Sie manuell in main, static bool firstPass = true; mehrere Male einfügen, wird der Compiler einen Fehler geben.)

  2. Wenn firstPassstatic ist, wird es erstellt und nur einmal initialisiert. Wenn Sie dieses Makro mehrmals verwenden, sollten Sie (abgesehen von der ersten Verwendung) keine Ergebnisse erzeugen, da das Flag auf false gesetzt wurde und es immer noch cout ist.

Ein bisschen verwirrt.

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

Ja gedruckt wird, Es ist schlecht, Makros anstelle von Funktionsvorlagen zu verwenden. – LogicStuff

+3

Dieser Code ist sinnlos. Jedes Mal, wenn du es anrufst, hast du einen neuen "FirstPass" aufgrund von Scoping-Regeln. – NathanOliver

+1

Ihr Missverständnis scheint mit dem Makroinhalt zu sein (speziell dem Block, '{...}') und nicht mit dem Makro selbst. Das heißt, wenn Sie den Makroinhalt manuell kopieren und einfügen, wie Sie es nennen, haben Sie das gleiche Problem, ohne dass Makros beteiligt sind. – chris

Antwort

4

Dieses Makro kann nicht wie vorgesehen funktionieren. Der Schlüssel, warum der Compiler es erlaubt, ist die { }, die die static bool firstPass umgibt. Dadurch wird ein neuer Bereich erstellt, in dem die neue Variable jede andere Variable mit diesem Namen ausblenden kann. Wenn dieser Bereich endet, ist die statische Komponente nicht mehr sichtbar.

Aufgrund der neuen Bereiche, das ist legal:

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

Dies würde die Art und Weise arbeiten, um es beabsichtigt war, durch Erst-Durchlauf aus dem Makro bewegt.

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

ETA: Oder vielleicht es funktioniert wie vorgesehen. Mit dem statischen Bool innerhalb des Makros wird jede Aufruf-Site ihre Ausgabe genau einmal ausgeben, da jede Aufruf-Site eine eigene Instanz des FirstPass-Flags besitzt. Mit dem statischen Bool außerhalb des Makros wird nur die erste Aufrufseite, die erreicht werden soll, ihre Ausgabe melden und nur beim ersten Mal, wenn sie erreicht wird.

Also mit dem static bool innerhalb des Makro,

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; 
} 

drucken

A 
B 
C 

aber mit dem statischen Bool außerhalb des Makro, es nur

A 
+0

Lustig; Ich würde sagen, es funktioniert genauso wie beabsichtigt. Beim ersten Aufruf von 'TESTING' wird gemeldet, dass es ausgeführt wird - und nicht danach. Aber dann wird die Frage "Was ist das beabsichtigte Verhalten". Wir sind beide richtig (für unsere Annahmen über das, was beabsichtigt ist); sie sind nur unterschiedliche Interpretationen oder Annahmen über das, was beabsichtigt ist. –

+0

Ahhhh, ich hatte nicht über die Absicht nachgedacht, nur das erste Mal über eine bestimmte Call-Site zu berichten. –