C中的>>> =运算符是什么?
由同事给出的一个难题,我不知道这个C程序是如何编译和运行的。 这是什么>>>=
运算符和奇怪的1P1
文字? 我已经在Clang和GCCtesting过了。 没有警告,输出是“???”
#include <stdio.h> int main() { int a[2]={ 10, 1 }; while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] ) printf("?"); return 0; }
该行:
while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] )
包含有向图 :>
和<:
:,分别翻译为]
和[
,所以它相当于:
while( a[ 0xFULL?'\0':-1 ] >>= a[ !!0X.1P1 ] )
文字0xFULL
与0xF
(hex为15
)相同; ULL
只是指定它是一个unsigned long long
文字 。 在任何情况下,作为一个布尔值是真的,所以0xFULL ? '\0' : -1
0xFULL ? '\0' : -1
计算结果为'\0'
,它是一个数字值仅为0
的字符 。
同时, 0X.1P1
是一个等于2/16 = 0.125的hex浮点数字 。 在任何情况下,非零,它也是一个布尔值,所以用两个否定它!!
再次产生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 ? '\0' : -1 ] >>= a[ !!0X.1P1 ] )
和一个更具可读性的版本,将它们所parsing的值replace为[]
的expression式:
while( a[0] >>= a[1] )
用它们的值代替a[0]
和a[1]
可以很容易地找出循环的作用,即相当于:
int i = 10; while( i >>= 1)
它在每次迭代中简单地执行(整数)除2,产生序列5, 2, 1
。
让我们通过从左到右的expression式:
a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ]
我注意到的第一件事就是我们使用三元运算符来使用?
。 所以这个子expression式:
0xFULL ? '\0' : -1
如果0xFULL
不为零,则返回'\0'
,否则返回-1
0xFULL
是一个hex字面值,带有无符号的long-long后缀 – 意味着它是一个unsigned long long
types的hex文字,这并不重要虽然,因为0xF
可以适应一个正则整数。
此外,三元运算符将第二和第三项的types转换为它们的通用types。 然后'\0'
被转换为int
,这只是0
。
0xF
的值比零大,所以通过。 expression现在变成:
a[ 0 :>>>=a<:!!0X.1P1 ]
接下来, :>
是一个有向图 。 这是一个扩展到]
的构造:
a[0 ]>>=a<:!!0X.1P1 ]
>>=
是有符号的右移运算符,我们可以将其从a
中排除,以使其更清楚。
而且, <:
是一个扩展为[
:
a[0] >>= a[!!0X.1P1 ]
0X.1P1
是一个带指数的hex文字。 但不pipe价值!!
任何非零的东西都是真的。 0X.1P1
是0.125
,它是非零的,所以它变成:
a[0] >>= a[true] -> a[0] >>= a[1]
>>=
是有符号的右移运算符。 它通过向右移动操作符右侧的值来改变左操作数的值。 十进制是1010
。 所以这里是步骤:
01010 >> 1 == 00101 00101 >> 1 == 00010 00010 >> 1 == 00001 00001 >> 1 == 00000
>>=
返回操作的结果,所以只要每次移位a[0]
保持非零,则循环将继续。 第四次尝试是a[0]
变为0
,所以循环从不input。
结果, ?
打印三次。