Ecco un esempio pertinente. Ovviamente non è valido C, ma mi sto occupando solo del preprocessore qui, quindi il codice in realtà non deve essere compilato.Durante l'espansione della macro C, esiste un caso speciale per macro che si espandono in "/ *"?
#define IDENTITY(x) x
#define PREPEND_ASTERISK(x) *x
#define PREPEND_SLASH(x) /x
IDENTITY(literal)
PREPEND_ASTERISK(literal)
PREPEND_SLASH(literal)
IDENTITY(*pointer)
PREPEND_ASTERISK(*pointer)
PREPEND_SLASH(*pointer)
Esecuzione preprocessore di GCC su di esso:
gcc -std=c99 -E macrotest.c
Questo produce:
(...)
literal
*literal
/literal
*pointer
**pointer
/*pointer
Si prega di notare lo spazio extra nell'ultima riga.
Sembra una funzionalità che impedisce ai macro di espandersi a "/ *", che sono sicuro sia ben intenzionato. Ma a colpo d'occhio, non sono riuscito a trovare nulla che riguardasse questo comportamento nello standard C99. Poi di nuovo, sono inesperto allo C. Qualcuno può fare luce su questo? Dove è specificato? Direi che un compilatore che aderisce al C99 non dovrebbe semplicemente inserire spazi extra durante l'espansione delle macro solo perché probabilmente impedirebbe errori di programmazione.
+1. Penso che l'intuizione chiave sia che l'output di -E infatti non è specificato dallo standard.Lo standard parla del programma costituito da una sequenza di token di preelaborazione, e successivamente viene convertito in una sequenza di token. Dipende interamente dal preprocessore come rappresentare quelle sequenze, e in questo caso come serializzarle su un file come una sequenza di * byte *. Ovviamente l'unica serializzazione valida è quella che verrà riletta come una serie equivalente di token di preelaborazione, così come dici tu, deve mettere uno spazio bianco tra due token che insieme formerebbero uno. –
Sono d'accordo al 100%, volevo scrivere qualcosa come la tua spiegazione ma non avevo dedicato tempo. –
Buona risposta, anche se ho due commenti nitidi: non esiste un token '/ *'; i commenti vengono rimossi dalla fonte prima di essere tokenizzati. Si potrebbe formare un token '++' da due token '+' usando '##'. –