2016-05-01 18 views
20

Ho trovato questo esempio di codice C, e sono assolutamente perplesso:C strano macro sintassi

#include <stdio.h> 
#define M(a,b) a%:%:b 

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", M(a,b)<:a:>); 
    printf("%d", M(a,b)<:a:>?a:b); 
    printf("%d", c=M(a,b)<:a:>?a:b); 
} 

Qualcuno potrebbe spiegare che cosa questo dovrebbe fare? Non si compila nemmeno in Visual Studio, ma l'ho eseguito online (su ideone.com) e ha stampato 2011, che ha anche aggiunto alla confusione.

+2

Eventuali duplicati di [cosa il C ??! ??! operatore do?] (http://stackoverflow.com/questions/7825055/what-does-the-c-operator-do) – GSerg

+4

È questo dal contest C offuscato? –

+0

non può spiegare, anche non ho visto prima. Compila in osx/darwin/unix. Per prima cosa, la prima riga valuta e stampa '20', seconda riga' 1', terza riga '1'. – user3078414

risposta

37

Sta facendo uso di C digraphs che erano modifiche allo standard C nel 1994 e quindi parte dello standard C99. Scambiare i digrammi con i loro caratteri effettivi, si ottiene:

#include <stdio.h> 
#define M(a,b) a##b 

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", M(a,b)[a]); 
    printf("%d", M(a,b)[a]?a:b); 
    printf("%d", c=M(a,b)[a]?a:b); 
} 

Quindi, tenere a mente che a##b si fonderanno insieme l'ingresso in un unico identificatore. Dal momento che la macro è appena passato a e b, il risultato è appena ab, in modo da avere in modo efficace:

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", ab[a]); 
    printf("%d", ab[a]?a:b); 
    printf("%d", c=ab[a]?a:b); 
} 

L'assegnazione di c non è davvero rilevante, in modo che può sbarazzarsi di che:

main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", ab[a]); 
    printf("%d", ab[a]?a:b); 
    printf("%d", ab[a]?a:b); 
} 

Ora, cerchiamo di sbarazzarsi del operatore ternario (?:), perché siamo in grado di lavorare fuori in modo statico (ab[a] è sempre vero, perché è a 1 e ab[1] è 20, vale a dire non-zero):

0.123.516,410617 millions
main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", ab[a]); 
    printf("%d", a); 
    printf("%d", a); 
} 

Ora, sostituire le variabili con i loro valori attuali, vale a dire con ab[a]20 e a con 1

main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", 20); 
    printf("%d", 1); 
    printf("%d", 1); 
} 
+7

impressionante analisi –

+3

Wow, questo apre un nuovo mondo di possibilità. : D Grazie! – Eutherpy

+58

@Eutherpy: No. No, non lo è. Fai finta di non averlo mai visto. –