2016-05-01 3 views
20

Я нашел C пример кода, и я совершенно озадачен:C странный макрос синтаксис

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

Может кто-нибудь объяснить, что это должен делать? Он даже не компилируется в Visual Studio, но я запустил его онлайн (на ideone.com), и он напечатал 2011, что также добавило к путанице.

+2

Возможный дубликат [Что делает C ??! ??! оператор делает?] (http://stackoverflow.com/questions/7825055/what-does-the-c-operator-do) – GSerg

+4

Это из обфускации C-конкурса? –

+0

не могу объяснить, также не видел раньше. Он компилируется в osx/darwin/unix. FYI, первая строка оценивает и печатает '20', вторую строку' 1', третью строку '1'. – user3078414

ответ

37

Он использует C digraphs, которые были поправками к стандарту C в 1994 году и, следовательно, частью стандарта C99. Перестановка орграфы с их реальными персонажами, вы получите:

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

Итак, имейте в виду, что a##b сольются вход в единый идентификатор. Поскольку макрос просто передается a и b, результат просто ab, так что вы эффективно иметь:

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

Присваивание c не очень актуальна, поэтому мы можем избавиться от этого:

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

Теперь давайте избавиться от троичного оператора (?:), потому что мы можем работать его статически (ab[a] всегда верно, потому что a является 1 и ab[1] составляет 20, то есть ненулевая):

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

Теперь замените переменные с их фактическими значениями, т.е. ab[a] с 20 и a с 1

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

впечатляющий анализ –

+3

Вау, это открывает совершенно новый мир возможностей. : D Спасибо! – Eutherpy

+58

@Eutherpy: Нет. Нет, нет. Представьте, что вы никогда этого не видели. –

Смежные вопросы