什么是C中的>>> =运算符?

本文翻译自:What is the >>>= operator in C?

Given by a colleague as a puzzle, I cannot figure out how this C program actually compiles and runs. 由同事作为一个谜题,我无法弄清楚这个C程序实际上是如何编译和运行的。 What is this >>>= operator and the strange 1P1 literal? 这是什么>>>=运算符和奇怪的1P1字面值? I have tested in Clang and GCC. 我在Clang和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 ] )
        printf("?");

    return 0;
}

#1楼

参考:https://stackoom.com/question/1IYqm/什么是C中的-运算符


#2楼

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, ie the equivalent of: 更换a[0]a[1]的值应该可以很容易地找出循环正在做什么,即相当于:

int i = 10;
while( i >>= 1)

which is simply performing (integer) division by 2 in each iteration, producing the sequence 5, 2, 1 . 这是在每次迭代中简单地执行(整数)除以2,产生序列5, 2, 1


#3楼

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 ); 文字0xFULL0xF15为十六进制)相同; the ULL just specifies that it's an unsigned long long literal . ULL只是指定它是一个unsigned long long文字 In any case, as a boolean it's true, so 0xFULL ? '\\0' : -1 在任何情况下,作为布尔值它是真的,所以0xFULL ? '\\0' : -1 0xFULL ? '\\0' : -1 evaluates to '\\0' , which is a character literal whose numerical value is simply 0 . 0xFULL ? '\\0' : -1计算结果为'\\0' ,这是一个字符文字,其数值只是0

Meanwhile, 0X.1P1 is a hexadecimal floating point literal equal to 2/16 = 0.125. 同时, 0X.1P1十六进制浮点文字,等于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 . 再次产生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: 在这种情况下,右操作数a[1]的值始终为1 ,因此它等效于:

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. a[0]的初始值为10.右移一次后,变为5,然后(向下舍入)2,然后是1,最后是0,此时循环结束。 Thus, the loop body gets executed three times. 因此,循环体被执行三次。


#4楼

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. 是在说:“如果0xFULL是非零,返回'\\0' ,否则-10xFULL是一个十六进制文字与无符号长隆后缀 -这意味着它的文本类型的十六进制unsigned long long ,这其实并不重要但是,因为0xF可以适合常规整数。

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 . 然后将'\\0'转换为int ,它只是0

The value of 0xF is way bigger than zero, so it passes. 0xF的值大于零,因此它通过。 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. >>=是签名的右移操作符,我们可以将其从a中移出以使其更清晰。

Moreover, <: is a digraph that expands to [ : 而且, <:是一个扩展为[ :的有向图

a[0] >>= a[!!0X.1P1 ]

0X.1P1 is a hexadecimal literal with an exponent. 0X.1P1是带有指数的十六进制文字。 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: 0X.1P10.125非零,因此变为:

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 . 二进制101010 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. >>=返回其操作的结果,因此只要移位a[0]每次将其位右移1时都保持非零,循环将继续。 The fourth attempt is where a[0] becomes 0 , so the loop is never entered. 第四次尝试是a[0]变为0 ,因此永远不会输入循环。

As a result, ? 结果, ? is printed three times. 打印三次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值