2016-05-01 1 views
20

J'ai trouvé C exemple de code, et je suis tout à fait perplexe:C étrange syntaxe macro

#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); 
} 

Quelqu'un pourrait-il expliquer ce que cela est censé faire? Il ne compile pas même dans Visual Studio, mais je l'ai couru en ligne (sur ideone.com) et il a imprimé 2011, qui a également ajouté à la confusion.

+2

double possible de [Qu'est-ce que le C ??! ??! opérateur faire?] (http://stackoverflow.com/questions/7825055/what-does-the-c-operator-do) – GSerg

+4

Est-ce que c'est un concours de C obscurci? –

+0

ne peut pas expliquer, n'ont pas non plus vu auparavant. Il compile dans osx/darwin/unix. FYI, première ligne évalue et imprime «20», deuxième ligne «1», troisième ligne «1». – user3078414

Répondre

37

Il utilise C digraphs qui étaient des amendements à la norme C en 1994 et qui font donc partie de la norme C99. Permutant les digraphs avec leurs personnages réels, vous obtenez:

#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); 
} 

Alors, gardez à l'esprit que a##b va fusionner l'entrée en un seul identifiant. Étant donné que la macro est juste passé a et b, le résultat est juste ab, de sorte que vous avez efficacement:

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'affectation à c est pas vraiment pertinent, afin que nous puissions se débarrasser de cette:

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); 
} 

maintenant, se débarrasser de l'opérateur ternaire (?:), parce que nous pouvons le travailler de manière statique (ab[a] est toujours vrai parce que a est 1 et ab[1] est de 20, soit non nul):

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

Maintenant, remplacez les variables par leurs valeurs réelles, à savoir ab[a] avec 20 et a avec 1

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

analyse impressionnante –

+3

Wow, cela ouvre un tout nouveau monde de possibilités. : D Merci! – Eutherpy

+58

@Eutherpy: Non. Non. Imaginez que vous n'avez jamais vu ça. –