Domanda

    

Questa domanda ha già una risposta qui:

         

Si consideri questo (terribile, terribile, non va bene, molto male) la struttura del codice:

#define foo(x) // commented out debugging code

// Misformatted to not obscure the point
if (a)
foo(a);
bar(a);

Ho visto preprocessore due compilatori generano risultati diversi su questo codice:

if (a)
bar(a);

e

if (a)
;
bar(a);

Ovviamente, questo è un male per una base di codice portabile.

La mia domanda: Qual è il preprocessore dovrebbe fare con questo? Elide commenti prima, o espandere le macro prima?

È stato utile?

Soluzione

Purtroppo, il href="http://eli-project.sourceforge.net/c_html/c.html" ANSI C specifica esclude specificamente qualsiasi funzionalità del preprocessore nella sezione 4 ( "Questa specifica descrive solo la lingua C. Essa non prevede né la biblioteca o il preprocessore.").

Il href="http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1124.pdf" specifica rel="noreferrer"> C99 gestisce questo esplicitamente , anche se. Le osservazioni sono sostituiti con un singolo spazio nella "fase di traduzione", che avviene prima della direttiva al preprocessore parsing. (Sezione 6.10 per maggiori dettagli).

VC ++ e la GNU C Compiler sia seguire questo paradigma - altri compilatori non può essere compatibile se 're vecchio, ma se si tratta di C99 compatibile, si dovrebbe essere al sicuro.

Altri suggerimenti

Come descritto nella questa copia-n-incollato decription delle fasi di traduzione in standard C99, rimuovendo commenti (sono sostituiti da un unico spazio vuoto) avviene in fase di traduzione 3, mentre direttive al preprocessore vengono manipolati e macro vengono espanse nella fase 4.

Nello standard C90 (che ho solo supporto cartaceo, quindi nessuna copia-n-incolla) queste due fasi avvengono nello stesso ordine, anche se la descrizione delle fasi di traduzione è leggermente differente in qualche particolare dal standard C99 -. il fatto che i commenti vengono rimossi e sostituiti da un singolo carattere spazio prima pre-elaborazione delle direttive sono gestite e le macro espanse non è diverso

Ancora una volta, lo standard C ++ ha queste 2 fasi avvengono nello stesso ordine.

Per quanto riguarda come i commenti '//' dovrebbero essere trattati, lo standard C99 dice che questo (6.4.9 / 2):

  

A parte all'interno di una costante carattere, una stringa letterale, o di un commento, i caratteri //   introdurre un commento che comprende tutti i caratteri multibyte fino a, ma non incluso, il   prossima nuova linea di carattere.

e Standard C ++ dice (2.7):

  

I caratteri // iniziano un commento, che termina con il prossimo ritorno a capo   carattere.

Così il vostro primo esempio è chiaramente un errore da parte di quel traduttore - il carattere ';' dopo il foo(a) dovrebbe essere mantenuta quando la macro foo() è espansa - i caratteri di commento non dovrebbero far parte dei 'contenuti' di the foo() macro.

Ma dal momento che siete di fronte a un traduttore buggy, si potrebbe desiderare di cambiare la definizione della macro a:

#define foo(x) /* junk */

per aggirare il bug.

Tuttavia (e sto andando alla deriva fuori tema qui ...), dal momento che la linea di giunzione (backslash poco prima di una nuova linea) si verifica prima che i commenti vengono elaborate, è possibile imbattersi in qualcosa di simile a questo pezzo di codice di brutto:

#define evil( x) printf( "hello "); // hi there, \
                 printf( "%s\n", x); // you!



int main( int argc, char** argv)
{
    evil( "bastard");

    return 0;
}

Il che potrebbe sorprendere chi lo ha scritto.

O, meglio ancora, provare quanto segue, scritto da qualcuno (! Certamente non io) che ama commenti box-style:

int main( int argc, char** argv)
{
                            //----------------/
    printf( "hello ");      // Hey, what the??/
    printf( "%s\n", "you"); // heck??         /
                            //----------------/
    return 0;
}

A seconda che le impostazioni predefinite del compilatore per l'elaborazione trigrammi o meno (compilatori si suppone, ma dal momento che trigrammi sorpresa quasi tutti coloro che li attraversa, alcuni compilatori decidono di spegnerli per impostazione predefinita), si può o non può ottenere il comportamento desiderato -. qualunque comportamento che è, ovviamente

MSDN , i commenti sono sostituiti con un singolo spazio nella fase tokenizzazione, che avviene prima della fase di pre-elaborazione dove vengono espansi macro.

Non mettere mai // commenti nelle macro. Se si deve mettere commenti, usare / * * /. Inoltre, si dispone di un errore nella macro:

#define foo(x) do { } while(0) /* junk */

In questo modo, foo è sempre sicuro da usare. Ad esempio:

if (some condition)
    foo(x);

non potrà mai gettare un errore del compilatore, indipendentemente dal fatto che foo è definito in una certa espressione.

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr / ## / cerr
#endif
  • lavorerà su alcuni compilatori (VC ++). Quando _TEST_ non è definito,

    _cerr ...

    sarà sostituito dalla riga di commento

    // cerr ...

Mi sembra di ricordare che il rispetto richiede tre passaggi:

  1. striscia
  2. espandere le macro
  3. striscia nuovamente

La ragione di questo ha a che fare con il compilatore di essere in grado di accettare .i file direttamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top