一位同事给出了一个谜题,我不知道这个C程序实际上是如何编译和运行的.这个>>>=
运算符和奇怪的1P1
字面是什么?我在郎和GCC做过测试.没有任何警告,输出为"?"
#include <stdio.h>
int main()
{
int a[2]={ 10, 1 };
while( a[ 0xFULL?'\0':-1:>>>=a<:!!0X.1P1 ] )
printf("?");
return 0;
}
一位同事给出了一个谜题,我不知道这个C程序实际上是如何编译和运行的.这个>>>=
运算符和奇怪的1P1
字面是什么?我在郎和GCC做过测试.没有任何警告,输出为"?"
#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 ] )
包含digraphs :>
和<:
,分别转换为]
和[
,因此相当于:
while( a[ 0xFULL?'\0':-1 ] >>= a[ !!0X.1P1 ] )
文字0xFULL
与0xF
相同(十六进制表示15
);ULL
只指定了it's an unsigned long long
literal.在任何情况下,作为一个布尔值,它是真的,所以0xFULL ? '\0' : -1
计算为'\0'
,这是一个character literal,其数值只是0
.
同时,0X.1P1
是hexadecimal floating point literal,等于2/16=0.125.在任何情况下,作为非零,它作为布尔值也是真的,所以用!!
求反两次,再次产生1
.因此,整个过程简化为:
while( a[0] >>= a[1] )
运算符>>=
是一个compound assignment位运算符,它将其左操作数右移右操作数给定的位数,并返回结果.在这种情况下,右操作数a[1]
的值始终为1
,因此它相当于:
while( a[0] >>= 1 )
或者,相当于:
while( a[0] /= 2 )
a[0]
的初始值是10.右移一次后,它变为5,然后(四舍五入)2,然后是1,最后是0,此时循环结束.因此,循环体执行三次.