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 longtypes的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。
结果, ? 打印三次。