一位同事给出的一个谜题,我无法弄清楚这个 C 程序实际上是如何编译和运行的。这个>>>=运算符和奇怪的1P1文字是什么?我已经在 Clang 和 GCC 中进行了测试。没有警告,输出为“???”
>>>=
1P1
#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(对于 16 进制表示15)相同;ULLjust 指定它是一个unsigned long long字面量。在任何情况下,作为布尔值它是真的,所以0xFULL ? '\0' : -1计算为'\0',它是一个字符文字,其数值是简单的0。
0xFULL
0xF
15
ULL
unsigned long long
0xFULL ? '\0' : -1
'\0'
0
同时,0X.1P1是一个十六进制浮点文字,等于 2/16 = 0.125。在任何情况下,它都是非零的,它作为布尔值也是正确的,所以用!!再次否定它两次会产生1. 因此,整个事情简化为:
0X.1P1
!!
1
while( a[0] >>= a[1] )
运算符>>=是一个复合赋值,它将其左操作数右移右操作数给出的位数,并返回结果。在这种情况下,右操作数a[1]总是有值1,所以它等价于:
>>=
a[1]
while( a[0] >>= 1 )
或者,等效地:
while( a[0] /= 2 )
的初始值为a[0]10。右移一次后变为5,然后(向下舍入)2,然后是1,最后是0,此时循环结束。因此,循环体被执行了 3 次。
a[0]