2012-05-21 20 views
10

Il seguente codice C++ compila e funziona come il programmatore previsto il GCC (4.0.4)macro del preprocessore come parametri per altre macro

#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)); */ 
} 

Tuttavia, le macro causano un errore di Microsoft Visual C++ Express 2010:

main.cpp (7): C4003 avviso: parametri effettivi insufficienti per la macro 'FOO'
main.cpp (7): l'errore C2059: errore di sintassi: ')'

Il problema sembra essere che il compilatore Microsoft, mentre gestisce la macro BAR internamente, non espande la macro BAZ ai parametri che potrebbero essere utilizzati come due parametri separati per la macro FOO.

Secondo lo standard, quale compilatore gestisce correttamente la situazione?

+0

Sembra che quello che stai davvero cercando sia [macro variadic] (http://en.wikipedia.org/wiki/Variadic_macro). – leftaroundabout

+3

@leftaroundabout non sembra che sia ... –

+3

@iammilind: Cosa manca dal capitolo 16 dello standard? Come non è uno standard 'reale'? –

risposta

12

Secondo 16.3.4 della norma ISO/IEC 14882: 2003 (C++ Stardard) espansione macro viene eseguita come segue:

  1. Macro invocazione viene sostituito con la lista di sostituzione della macro (il corpo) in cui ogni nome di parametro (a meno che non sia influenzato da # o ##) viene sostituito con un'espansione macro completa dell'argomento corrispondente specificato nell'invocazione della macro.
  2. Il risultato del passaggio 1 è annullato. Se ci sono più invocazioni di macro in esso (eccetto quelle già espanse prendendo in considerazione il testo), esse vengono espanse secondo la stessa procedura in modo ricorsivo.

La sequenza di passi per il codice specificato è:

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

Così GCC è giusto, e VC non è. Ma l'errore che VC lamenta è che FOO ha 3 argomenti e BAR specifica solo 2 di essi. Apparentemente, VC cerca di individuare gli errori il prima possibile e se ne va un po 'troppo in là.

+1

Non capisco come l'algoritmo che hai fornito corrisponda al comportamento GCC. Se lo leggo correttamente, l'algoritmo procede come segue: 'BAR (BAZ)' è un'invocazione di 'BAR' con l'argomento' BAZ', quindi viene sostituito con 'FOO (BAZ, 1)'. Questo ora viene rieseguito. La prima macro trovata è 'FOO', quindi ora tenta di espandere' FOO' con gli argomenti 'BAZ' e' 1'. Questo non è un argomento sufficiente, quindi la preelaborazione fallisce. Perché riscanning 'FOO (BAZ, 1)' espande prima il 'BAZ', quando la scansione di' BAR (BAZ) 'ha esteso prima la' BAR'? – Mankarse

+0

@Mankarse Grazie, non è stato abbastanza chiaro. Fisso. –

+0

Grazie per la spiegazione chiara e completa. Ho imparato molto. – Mankarse

Problemi correlati