What is the >>>= operator in C?

帅比萌擦擦* 提交于 2019-12-02 13:46:40
Ilmari Karonen

The line:

while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] )

contains the digraphs :> and <:, which translate to ] and [ respectively, so it's equivalent to:

while( a[ 0xFULL?'\0':-1 ] >>= a[ !!0X.1P1 ] )

The literal 0xFULL is the same as 0xF (which is hex for 15); the ULL just specifies that it's an unsigned long long literal. In any case, as a boolean it's true, so 0xFULL ? '\0' : -1 evaluates to '\0', which is a character literal whose numerical value is simply 0.

Meanwhile, 0X.1P1 is a hexadecimal floating point literal equal to 2/16 = 0.125. In any case, being non-zero, it's also true as a boolean, so negating it twice with !! again produces 1. Thus, the whole thing simplifies down to:

while( a[0] >>= a[1] )

The operator >>= is a compound assignment that bit-shifts its left operand right by the number of bits given by the right operand, and returns the result. In this case, the right operand a[1] always has the value 1, so it's equivalent to:

while( a[0] >>= 1 )

or, equivalently:

while( a[0] /= 2 )

The initial value of a[0] is 10. After shifting right once, it become 5, then (rounding down) 2, then 1 and finally 0, at which point the loop ends. Thus, the loop body gets executed three times.

It is some rather obscure code involving digraphs, namely <: and :> which are alternative tokens for [ and ] respectively. There is also some use of the conditional operator. There is also a bit shifting operator, the right shift assignment >>=.

This is a more readable version:

while( a[ 0xFULL ? '\0' : -1 ] >>= a[ !!0X.1P1 ] )

and an even more readable version, replacing the expressions in the [] for the values they resolve to:

while( a[0] >>= a[1] )

Replacing a[0] and a[1] for their values should make it easy to figure out what the loop is doing, i.e. the equivalent of:

int i = 10;
while( i >>= 1)

which is simply performing (integer) division by 2 in each iteration, producing the sequence 5, 2, 1.

Let's go through the expression left-to-right:

a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ]

The first thing I notice is that we are using the ternary operator from the use of ?. So the subexpression:

0xFULL ? '\0' : -1

is saying "if 0xFULL is non-zero, return '\0', otherwise -1. 0xFULL is a hexadecimal literal with the unsigned long-long suffix - meaning it's a hexadecimal literal of type unsigned long long. That doesn't really matter though, because 0xF can fit inside a regular integer.

Also, the ternary operator converts the types of the second and third terms to their common type. '\0' is then converted to int, which is just 0.

The value of 0xF is way bigger than zero, so it passes. The expression now becomes:

a[ 0 :>>>=a<:!!0X.1P1 ]

Next, :> is a digraph. It is a construct that expands to ]:

a[0 ]>>=a<:!!0X.1P1 ]

>>= is the signed right shift operator, we can space that out from a to make it clearer.

Moreover, <: is a digraph that expands to [:

a[0] >>= a[!!0X.1P1 ]

0X.1P1 is a hexadecimal literal with an exponent. But no matter the value, the !! of anything that's non-zero is true. 0X.1P1 is 0.125 which is non-zero, so it becomes:

a[0] >>= a[true]
-> a[0] >>= a[1]

The >>= is the signed right shift operator. It changes the value of its left operand by shifting its bits forward by the value on the operator's right side. 10 in binary is 1010. So here are the steps:

01010 >> 1 == 00101
00101 >> 1 == 00010
00010 >> 1 == 00001
00001 >> 1 == 00000

>>= returns the result of its operation, so as long as shifting a[0] remains non-zero for every time its bits are shifted right by one, the loop will continue. The fourth attempt is where a[0] becomes 0, so the loop is never entered.

As a result, ? is printed three times.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!