Domanda

Ad esempio, è possibile:

#define definer(x) #define #x?
È stato utile?

Soluzione

Sebbene la sintassi non sia valida, la risposta alla tua domanda è tecnicamente sì. Ma può essere realizzato solo con cattivi trucchi che rendono il tuo codice illeggibile e irraggiungibile.

Vedi anche: http://www.ioccc.org/years.html#1995_vanschnitz e http://www.ioccc.org/years.html#2004_vik2

Altri suggerimenti

No, non puoi farlo.
Il simbolo della sterlina (#) ha un significato diverso mentre si trova in una definizione. significa - se questo è un argomento, trasformalo in una stringa citandolo.

Non è possibile nidificare le direttive del preprocessore C. Fortunatamente, non è quasi mai necessario. Se hai davvero bisogno di quel tipo di potere, starai sicuramente meglio con un altro preprocessore che si esegue prima di passare il codice al compilatore C. Ad esempio:

sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c

Un altro trucco utile è isolare il trucco in un singolo file di intestazione, che è generato da un programma che scrivi tu:

./generate-trickery --greet 'J. Random Person' > foo.h

dove foo.h assomiglierà a qualcosa del genere:

#define GREET(x) ("J. Random Person greets you, " #x)

Se lo colleghi con un Makefile o con qualche altra automazione, lo sarà piuttosto semplice e non inciampare molto nel tuo sviluppo.

No, non puoi farlo.

Puoi fare riferimento a una macro da un'altra, ma non puoi definire una macro da un'altra.

Se stai cercando di creare un segmento di codice del preprocessore che può essere chiamato più volte per eseguire cose leggermente diverse, un modo (moderatamente terribile) che puoi fare è isolare il codice in un singolo .h file che quindi #include più volte. L'idea è che ogni volta che #define il file sei & Quot; chiamando la tua routine & Quot; - tu " passa argomenti " innanzitutto ENUMVAL() inserendo alcune costanti del preprocessore a cui fa riferimento il file incluso.

Un posto in cui l'ho visto utile è la generazione di " smart " enumerazioni che possono essere convertite in / dal loro " stringized " moduli (utile per l'I / O). Si crea un enum file contenente ad esempio

ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)

e successivamente <=> questo file due volte: una volta in cui <=> è definito in modo da creare una <=> dichiarazione e una volta quando <=> è definito in modo da produrre un array di nomi rigorosi. In questo modo, non è necessario specificare l'elenco dei token effettivi più di una volta.

#define definer(x) #define #x?

#x è una stringa di x. Non è possibile #definire un token stringa. (#define " foo " ;.) Deve essere un identificativo [a-zA-Z0-9 _] * token.

Non puoi non nidificare # definisci così. Non puoi avere un #define in un #define.

Puoi puoi avere # if all'interno di #if blocchi.

#ifdef FOO

#ifdef BAR
 ...
#else // BAR
 ...
#endif // BAR

#else // FOO
 ...
#endif //FOO

Sei anche un po 'limitato per quanto riguarda le espressioni che puoi usare nelle macro #if. Ma a volte puoi aggirare questo. Ad esempio:

        /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]

Più qualcosa di simile:

STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );

(Sì, so di #include < stdint.h > . È solo un esempio.)

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