Давайте пройдемся по выражению слева направо:
a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ]
Первое, что я заметил, это то, что мы используем троичный оператор от использования ?
. Итак, подвыражение:
0xFULL ? '\0' : -1
говорит "если 0xFULL
не ноль, возвращайте '\0'
, в противном случае -1
. 0xFULL
это шестнадцатеричный литерал с беззнаковым длинным-длинным суффиксом - это означает, что это шестнадцатеричный литерал типа unsigned long long
. Это на самом деле не имеет значения, потому что 0xF
может помещаться внутри обычного целого числа.
Кроме того, троичный оператор преобразует типы второго и третьего членов в их общий тип. '\0'
затем преобразуется в int
, что просто 0
.
Значение 0xF
намного больше нуля, поэтому оно проходит. Выражение теперь становится:
a[ 0 :>>>=a<:!!0X.1P1 ]
Далее :>
идет орграф . Это конструкция, которая расширяется до ]
:
a[0 ]>>=a<:!!0X.1P1 ]
>>=
является подписанным оператором сдвига вправо, мы можем выделить его, a
чтобы сделать его более понятным.
Кроме того, <:
это орграф, который расширяется до [
:
a[0] >>= a[!!0X.1P1 ]
0X.1P1
является шестнадцатеричным литералом с показателем степени. Но независимо от значения, !!
все, что не равно нулю, верно. 0X.1P1
это 0.125
ненулевое значение, поэтому оно становится:
a[0] >>= a[true]
-> a[0] >>= a[1]
Это >>=
подписанный оператор правого сдвига. Он изменяет значение своего левого операнда, сдвигая свои биты вперед на значение с правой стороны оператора. 10
в двоичном есть 1010
. Итак, вот шаги:
01010 >> 1 == 00101
00101 >> 1 == 00010
00010 >> 1 == 00001
00001 >> 1 == 00000
>>=
возвращает результат своей операции, поэтому, пока смещение a[0]
остается ненулевым, каждый раз, когда его биты сдвигаются вправо на единицу, цикл будет продолжаться. Четвертая попытка заключается в том, где a[0]
делается 0
, поэтому цикл никогда не вводится.
В результате ?
печатается три раза.