obfuscation – What is the >>>= operator in C?

The Question :

295 people think this question is useful

Given by a colleague as a puzzle, I cannot figure out how this C program actually compiles and runs. What is this >>>= operator and the strange 1P1 literal? I have tested in Clang and GCC. There are no warnings and the output is “???”

#include <stdio.h>

int main()
    int a[2]={ 10, 1 };

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

    return 0;

The Question Comments :
  • Some of those are digraphs.
  • @Kay, no in this case: :> = ] then a[…] >> = a[…]
  • @Marc I don’t think it can be “>> >=” because that wouldn’t compile, however the above code actually compiles.
  • The 0x.1P1 is a hexadecimal literal with an exponent. The 0x.1 is the number part, or 1/16 here. The number after the ‘P’ is the power of two the number is multiplied by. So 0x.1p1 is really 1/16 * 2, or 1/8. And if you were wondering about 0xFULL that’s just 0xF, and ULL is the suffix for an unsigned long long
  • C syntax — endless material for pundits and trivia lovers, but ultimately not all that important.

The Answer 1

469 people think this answer is useful

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.

The Answer 2

69 people think this answer is useful

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.

The Answer 3

42 people think this answer is useful

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.

Add a Comment