Подтвердить что ты не робот

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, который также добавил к путанице.

4b9b3361

Ответ 1

Он использовал C-орграфы, которые были поправками к стандарту 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 );
}