Domanda

Perché questi blocchi di codice producono diversi risultati?

Qualche codice comune:

#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)
.

Caso 1:

#define GLUE(a,b,c) a##b##c  
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"
.

Caso 2:

#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"
.

Caso 3:

#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"
.

Sto usando MSVC ++ da VS.NET 2005 SP1

Modifica: Attualmente è la mia convinzione che il preprocessore funzioni in questo modo quando si espande le macro: Passo 1: - Prendi il corpo - Rimuovere qualsiasi spazio bianco attorno agli operatori ## - Analizza la stringa, nel caso in cui venga trovato un identificatore che corrisponde al nome di un parametro: -Se è vicino a un operatore ##, sostituire l'identificatore con il valore letterale del parametro (cioè la stringa passata) -Se non è accanto a un operatore ##, eseguire questo intero processo di spiegazione sul valore del parametro in primo luogo, quindi sostituire l'identificatore con quel risultato. (ignorando il custodia SingleFy Single "#" ATM) -Rimuovere tutti i ## operatori

Step 2: - Prendi quella stringa risultante e analizzalo per qualsiasi macro

Ora, da quello credo che tutti e 3 i casi dovrebbero produrre la stessa identica stringa risultante:

part1part2 *

E quindi dopo il passaggio 2, dovrebbe provocare

Lavori *

Ma almeno dovrebbe causare la stessa cosa.

È stato utile?

Soluzione

Casi 1 e 2 non hanno alcun comportamento definito poiché si tentano di incollare un * in un token preprocessore. Secondo le regole di associazione del preprocessore, si tenta di colla insieme dei token PART1PART2 (o solo PART2) e *. Nel tuo caso, questo probabilmente fallisce in silenzio, il che è uno dei possibili risultati quando le cose non sono definite. Il token PART1PART2 seguito da * non sarà quindi considerato per la macro espansione. Stringa è quindi produce il risultato che vedi.

Il mio GCC si comporta in modo diverso sui tuoi esempi:

/usr/bin/gcc -O0 -g -std=c89 -pedantic   -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"
.

Pertanto per riassumere il tuo caso 1 ha due problemi.

    .
  • incollando due token che non risultano in un token preprocessore valido.
  • Ordine di valutazione dell'operatore ##

Nella causa 3, il tuo compilatore sta dando il risultato sbagliato. Dovrebbe

    .
  1. Valuta gli argomenti a STRINGAFY1
  2. per fare che deve espandere GLUE
  3. GLUE Risultati in PART1PART2*
  4. che deve essere espanso di nuovo
  5. Il risultato è works*
  6. che poi è passato a STRINGAFY1

Altri suggerimenti

Sta facendo esattamente quello che stai dicendo di farlo.Il primo e il secondo prendere i nomi dei simboli passati e incollali insieme in un nuovo simbolo.Il terzo prende 2 simboli e li insegue, allora stai mettendo il * nella corda da soli (che alla fine valuterà in qualcos'altro).

Qual è esattamente la domanda con i risultati?Cosa ti aspettavi di ottenere?Tutto sembra funzionare come mi aspetterei.

Allora ovviamente è la domanda del perché stai giocando con le arti scure del simbolo comunque in questo modo?:)

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