Что такое оператор>= в C?
данный коллегой как головоломка, я не могу понять, как эта программа C на самом деле компилируется и запускается. Что это такое >>>=
оператор и странный 1P1
литерал? Я протестировал в Clang и GCC. Нет никаких предупреждений и выход "???"
#include <stdio.h>
int main()
{
int a[2]={ 10, 1 };
while( a[ 0xFULL?'':-1:>>>=a<:!!0X.1P1 ] )
printf("?");
return 0;
}
3 ответа:
строку:
while( a[ 0xFULL?'':-1:>>>=a<:!!0X.1P1 ] )
содержит орграфы
:>
и<:
, что переводится как]
и[
соответственно, так что это эквивалентно:while( a[ 0xFULL?'':-1 ] >>= a[ !!0X.1P1 ] )
в прямом
0xFULL
это то же самое, что0xF
(который является наговор на15
); theULL
просто указывает, что этоunsigned long long
литерал. В любом случае, как логическое это правда, так0xFULL ? '' : -1
оценивает в''
, который является символьный литерал чье числовое значение просто0
.между тем,
0X.1P1
это шестнадцатеричный литерал с плавающей запятой равна 2/16 = 0.125. В любом случае, будучи ненулевым, это также верно как булево, поэтому отрицание его дважды с!!
снова производит1
. Таким образом, все это упрощается до:while( a[0] >>= a[1] )
оператор
>>=
это составное задание этот бит-сдвигает свой левый операнд вправо на количество битов, заданных правый операнд и возвращает результат. В этом случае правильный операндa[1]
имеет значение1
, так что это эквивалентно:while( a[0] >>= 1 )
или, что то же самое:
while( a[0] /= 2 )
начальное значение
a[0]
это 10. После сдвига вправо один раз он становится 5, затем (округление вниз) 2, затем 1 и, наконец, 0, в этот момент цикл заканчивается. Таким образом, тело цикла выполняется три раза.
это какой-то довольно непонятный код с участием орграфы, а именно
<:
и:>
которые являются альтернативными маркерами для[
и]
соответственно. Существует также некоторое использование условный оператор. Существует также оператор сдвига битов, назначение правой смены>>=
.это более читаемая версия:
while( a[ 0xFULL ? '' : -1 ] >>= a[ !!0X.1P1 ] )
и даже больше читаемая версия, заменяющая выражения в
[]
для значений, которые они разрешают:while( a[0] >>= a[1] )
замена
a[0]
иa[1]
для их значений должно быть легко понять, что делает цикл, т. е. эквивалент:int i = 10; while( i >>= 1)
который просто выполняет (целочисленное) деление на 2 в каждой итерации, производя последовательность
5, 2, 1
.
давайте пройдемся по выражению слева направо:
a[ 0xFULL?'':-1:>>>=a<:!!0X.1P1 ]
первое, что я замечаю, что мы используем тернарный оператор от использования
?
. Итак, подвыражение:0xFULL ? '' : -1
говорит: "Если
0xFULL
не равно нулю, возврат''
, иначе-1
.0xFULL
- это шестнадцатеричный литерал с беззнаковый длинный-длинный суффикс - означает, что это шестнадцатеричный литерал типаunsigned long long
. Это действительно не имеет большого значения, хотя, потому что0xF
может поместиться внутри обычного целого числа.кроме того, тернарный оператор преобразует типы второго и третьего членов в их общий тип.
''
затем преобразуется в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]
The
>>=
является подписанным оператором сдвига вправо. Он изменяет значение своего левого операнд, смещая его биты вперед на значение с правой стороны оператора.10
в двоичном виде это1010
. Итак, вот шаги:01010 >> 1 == 00101 00101 >> 1 == 00010 00010 >> 1 == 00001 00001 >> 1 == 00000
>>=
возвращает результат своей работы, так как пока смещениеa[0]
остается ненулевым для каждого раза, когда его биты сдвигаются вправо на единицу, цикл будет продолжаться. Четвертая попытка-это гдеa[0]
становится0
, поэтому цикл никогда не вводится.в результате
?
напечатано три раза.