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

Почему int _ $[: >= <% -!. 0,}; компилировать?

Сегодня я нашел странный синтаксис, например

 int _$[:>=<%-!.0,};

в некотором старом коде, но на самом деле код не комментируется. Кажется, нет отчета об ошибках компиляции для этой строки. Я тестировал его отдельно, и он тоже может компилироваться:

int main(){
    int _$[:>=<%-!.0,};
    return 0;
}

Почему это возможно?

4b9b3361

Ответ 1

С Диграф (см. ниже) линия преобразуется в:

int _$[]={-!.0,};

С правой стороны .0 - это литерал double, ! - оператор логического отрицания, - - оператор арифметического отрицания, а , - конечная запятая. Вместе {-!.0,} является инициализатором массива.

Левая часть int _$[] определяет массив int. Тем не менее, существует одна последняя проблема, _$ не является допустимым идентификатором в стандартном C. Некоторые компиляторы (например, gcc) поддерживают его как расширение.


C11 §6.4.6 Пункторы

Во всех аспектах языка шесть жетонов

<: :> <% %> %: %:%:

ведут себя соответственно так же, как шесть токенов

[  ]  {  }  #  ##

Ответ 2

Ну,

  • underscore _ является символом разрешенного идентификатора,
  • Знак доллара $ разрешен и в некоторых реализациях,
  • левая скобка [ означает, что тип должен быть массивом,
  • :> является орграфом для ],
  • equals = - это назначение,
  • <% является орграфом для {,
  • -!.0 является просто -1 (.0 является двойным литералом 0.0, ! неявно переходит к (int) 0 и логически инвертирует его, а - является отрицательным),
  • у вас могут быть запятые в инициализаторах массива {1, (2, 3,)},
  • и ; завершает утверждение.,

Итак, вы получаете

int _$[] = {-1,};

Ответ 3

Это работает благодаря digraphs в C. Соответствующая строка декодирует вот так:

int _$ [ :> = <% - ! .0  , } ;
int _$ [ ]  = {  - ! 0.0 , } ;

Далее

  • .0 является литералом double.
  • ! - оператор булевого отрицания, поэтому !.0 дает (int) 1.
  • - - это оператор унарного оператора отрицания, который дает (int) -1.
  • Конечная запятая является законной после элемента массива.

Ответ 4

Если мы заменим в вашей строке кода орграфы :> и <%, мы получим

int _$[]={-!.0,};

что эквивалентно

int _$[] = { -1, };

Это объявление массива _$ типа int [1] с инициализатором.

Обратите внимание, что это точно не гарантируется для компиляции, поскольку стандартный язык C не обеспечивает немедленную поддержку символа $ в индексах. Тем не менее, он позволяет реализациям расширять набор поддерживаемых символов. По-видимому, используемый вами компилятор поддерживал $ в идентификаторах.