Почему int _ $[: >= <% -!. 0,}; компилировать?
Сегодня я нашел странный синтаксис, например
int _$[:>=<%-!.0,};
в некотором старом коде, но на самом деле код не комментируется. Кажется, нет отчета об ошибках компиляции для этой строки. Я тестировал его отдельно, и он тоже может компилироваться:
int main(){
int _$[:>=<%-!.0,};
return 0;
}
Почему это возможно?
Ответы
Ответ 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 не обеспечивает немедленную поддержку символа $
в индексах. Тем не менее, он позволяет реализациям расширять набор поддерживаемых символов. По-видимому, используемый вами компилятор поддерживал $
в идентификаторах.