2012-05-21 13 views
10

Der folgende C++ Code kompiliert und arbeitet als Programmierer auf GCC bestimmt (4.0.4)Präprozessormakros als Parameter an andere Makros

#define FOO(x,y,z) ((x)*(y)*(z)) 
#define BAR(x) FOO(x,1) 
#define BAZ 3,7 

int main() 
{ 
    return BAR(BAZ); /* interpreted as return ((3)*(7)*(1)); */ 
} 

Jedoch verursachen die Makros einen Fehler auf Microsoft Visual C++ Express 2010:

main.cpp (7): Warnung C4003: nicht genug, um aktuelle Parameter für den Makro 'foo'
main.cpp (7): error C2059: Syntaxfehler: ')'

Das Problem scheint zu sein, dass der Microsoft-Compiler bei der internen Verarbeitung des BAR-Makros den BAZ-Makro nicht auf Parameter erweitert, die als zwei separate Parameter für Makro-FOO verwendet werden könnten.

Gemäß dem Standard, welcher Compiler behandelt die Situation korrekt?

+0

Scheint so, als ob Sie wirklich suchen [Variadic Makros] (http://en.wikipedia.org/wiki/Variadic_macro). – leftaroundabout

+3

@leftaroundabout es scheint nicht wie er ist ... –

+3

@iammilind: Was fehlt in Kapitel 16 des Standards? Wie ist es kein "echter" Standard? –

Antwort

12

Nach 16.3.4 der ISO/IEC 14882: 2003 (C++ Stardard) Makroerweiterung wird wie folgt ausgeführt:

  1. Makro-Aufruf mit dem Makros Ersatzliste ersetzt wird (der Körper), wobei jeder Parametername (Es sei denn, es wird von # oder ## beeinflusst) wird durch eine vollständige Makroerweiterung des entsprechenden Arguments ersetzt, das im Makroaufruf angegeben ist.
  2. Das Ergebnis von Schritt 1 ist erneut gescannt. Wenn es mehr Makroaufrufe gibt (außer den bereits expandierten, die den betrachteten Text erhalten), werden sie entsprechend der gleichen Prozedur rekursiv erweitert.

Die Reihenfolge der Schritte für den Code ist, dass Sie angegeben:

  1. BAR(BAZ)
  2. FOO(3,7,1)
  3. ((3)*(7)*(1))

So GCC richtig ist, und VC nicht. Aber der Fehler, über den sich VC beschwert, ist, dass FOO 3 Argumente hat und BAR nur 2 davon angibt. VC versucht scheinbar so schnell wie möglich Fehler zu finden und geht ein bisschen zu weit hinein.

+1

Ich verstehe nicht, wie der Algorithmus, den Sie angegeben haben, dem GCC-Verhalten entspricht. Wenn ich es richtig lese, läuft der Algorithmus wie folgt ab: 'BAR (BAZ)' ist ein Aufruf von 'BAR' mit dem Argument' BAZ', wird also durch 'FOO (BAZ, 1)' ersetzt. Dies wird jetzt erneut gescannt. Das erste Makro, das es findet, ist 'FOO', also versucht es nun,' FOO' mit den Argumenten 'BAZ' und' 1' zu erweitern. Dies ist nicht genug Argumente, daher schlägt die Vorverarbeitung fehl. Warum erweitert Rescan 'FOO (BAZ, 1) 'zuerst die' BAZ ', beim Scannen von' BAR (BAZ) 'zuerst die' BAR'? – Mankarse

+0

@Mankarse Danke, es war wirklich nicht klar genug. Fest. –

+0

Danke für die klare und vollständige Erklärung. Ich hab viel gelernt. – Mankarse