Перейдемо до виразу зліва направо:
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
, тому цикл ніколи не вводиться.
Як результат, ?
друкується три рази.