Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
584 views
in Technique[技术] by (71.8m points)

operators - 什么是按位移位(位移)运算符以及它们如何工作?(What are bitwise shift (bit-shift) operators and how do they work?)

I've been attempting to learn C in my spare time, and other languages (C#, Java, etc.) have the same concept (and often the same operators) ...

(我一直在尝试在业余时间学习C语言,其他语言(C#,Java等)具有相同的概念(通常是相同的运算符)......)

What I'm wondering is, at a core level, what does bit-shifting ( << , >> , >>> ) do, what problems can it help solve, and what gotchas lurk around the bend?

(我想知道的是,在核心层面,位移( <<>>>>> )做了什么,它有什么问题可以帮助解决,以及潜伏在弯道的东西?)

In other words, an absolute beginner's guide to bit shifting in all its goodness.

(换句话说,一个绝对的初学者指导比特移位的所有优点。)

  ask by John Rudy translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The bit shifting operators do exactly what their name implies.

(比特移位运算符正如其名称所暗示的那样。)

They shift bits.

(他们转移位。)

Here's a brief (or not-so-brief) introduction to the different shift operators.

(以下是对不同班次运营商的简要介绍(或不那么简短)。)

The Operators (运营商)

  • >> is the arithmetic (or signed) right shift operator.

    (>>是算术(或签名)右移运算符。)

  • >>> is the logical (or unsigned) right shift operator.

    (>>>是逻辑(或无符号)右移运算符。)

  • << is the left shift operator, and meets the needs of both logical and arithmetic shifts.

    (<<是左移运算符,满足逻辑和算术移位的需要。)

All of these operators can be applied to integer values ( int , long , possibly short and byte or char ).

(所有这些运算符都可以应用于整数值( intlong ,可能是shortbytechar )。)

In some languages, applying the shift operators to any datatype smaller than int automatically resizes the operand to be an int .

(在某些语言中,将移位运算符应用于任何小于int数据类型会自动将操作数调整为int 。)

Note that <<< is not an operator, because it would be redundant.

(请注意<<<不是运算符,因为它是多余的。)

Also note that C and C++ do not distinguish between the right shift operators .

(另请注意, C和C ++不区分右移运算符 。)

They provide only the >> operator, and the right-shifting behavior is implementation defined for signed types.

(它们仅提供>>运算符,右移行为是为签名类型定义的实现。)

The rest of the answer uses the C# / Java operators.

(答案的其余部分使用C#/ Java运算符。)

(In all mainstream C and C++ implementations including gcc and clang/LLVM, >> on signed types is arithmetic. Some code assumes this, but it isn't something the standard guarantees. It's not undefined , though; the standard requires implementations to define it one way or another. However, left shifts of negative signed numbers is undefined behaviour (signed integer overflow). So unless you need arithmetic right shift, it's usually a good idea to do your bit-shifting with unsigned types.)

((在包括gcc和clang / LLVM在内的所有主流C和C ++实现中,有关签名类型的>>是算术的。有些代码假设这一点,但它不是标准保证的东西。但它并不是未定义的 ;标准要求实现定义但是,负数有符号数的左移未定义的行为(有符号整数溢出)。所以除非你需要算术右移,否则用无符号类型进行位移通常是一个好主意。))


Left shift (<<) (左移(<<))

Integers are stored, in memory, as a series of bits.

(整数在内存中存储为一系列位。)

For example, the number 6 stored as a 32-bit int would be:

(例如,存储为32位int的数字6将是:)

00000000 00000000 00000000 00000110

Shifting this bit pattern to the left one position ( 6 << 1 ) would result in the number 12:

(将此位模式移动到左侧一个位置( 6 << 1 )将导致数字12:)

00000000 00000000 00000000 00001100

As you can see, the digits have shifted to the left by one position, and the last digit on the right is filled with a zero.

(如您所见,数字向左移动了一个位置,右边的最后一个数字用零填充。)

You might also note that shifting left is equivalent to multiplication by powers of 2. So 6 << 1 is equivalent to 6 * 2 , and 6 << 3 is equivalent to 6 * 8 .

(你可能还会注意到左移相当于乘以2的幂。所以6 << 1相当于6 * 2 6 << 3相当于6 * 8 。)

A good optimizing compiler will replace multiplications with shifts when possible.

(一个好的优化编译器会在可能的情况下用乘法替换乘法。)

Non-circular shifting (非圆形换档)

Please note that these are not circular shifts.

(请注意,这些不是循环转换。)

Shifting this value to the left by one position ( 3,758,096,384 << 1 ):

(将此值向左移动一个位置( 3,758,096,384 << 1 ):)

11100000 00000000 00000000 00000000

results in 3,221,225,472:

(结果为3,221,225,472:)

11000000 00000000 00000000 00000000

The digit that gets shifted "off the end" is lost.

(“失去结束”的数字将丢失。)

It does not wrap around.

(它没有环绕。)


Logical right shift (>>>) (逻辑右移(>>>))

A logical right shift is the converse to the left shift.

(逻辑右移与左移相反。)

Rather than moving bits to the left, they simply move to the right.

(它们不是向左移动位,而是向右移动。)

For example, shifting the number 12:

(例如,移动数字12:)

00000000 00000000 00000000 00001100

to the right by one position ( 12 >>> 1 ) will get back our original 6:

(向右移动一个位置( 12 >>> 1 )将取回原来的6个:)

00000000 00000000 00000000 00000110

So we see that shifting to the right is equivalent to division by powers of 2.

(所以我们看到向右移动相当于2的幂除法。)

Lost bits are gone (丢失的位消失了)

However, a shift cannot reclaim "lost" bits.

(但是,班次无法回收“丢失”的位。)

For example, if we shift this pattern:

(例如,如果我们改变这种模式:)

00111000 00000000 00000000 00000110

to the left 4 positions ( 939,524,102 << 4 ), we get 2,147,483,744:

(在左边4个位置( 939,524,102 << 4 ),我们得到2,147,483,744:)

10000000 00000000 00000000 01100000

and then shifting back ( (939,524,102 << 4) >>> 4 ) we get 134,217,734:

(然后换回( (939,524,102 << 4) >>> 4 )我们得到134,217,734:)

00001000 00000000 00000000 00000110

We cannot get back our original value once we have lost bits.

(一旦我们丢失了比特,我们就无法取回原来的价值。)


Arithmetic right shift (>>) (算术右移(>>))

The arithmetic right shift is exactly like the logical right shift, except instead of padding with zero, it pads with the most significant bit.

(算术右移与逻辑右移非常相似,除了用零填充代替填充,它填充最高有效位。)

This is because the most significant bit is the sign bit, or the bit that distinguishes positive and negative numbers.

(这是因为最重要的位是符号位,或区分正数和负数的位。)

By padding with the most significant bit, the arithmetic right shift is sign-preserving.

(通过使用最高有效位填充,算术右移是符号保留的。)

For example, if we interpret this bit pattern as a negative number:

(例如,如果我们将此位模式解释为负数:)

10000000 00000000 00000000 01100000

we have the number -2,147,483,552.

(我们有-2,147,483,552。)

Shifting this to the right 4 positions with the arithmetic shift (-2,147,483,552 >> 4) would give us:

(用算术移位(-2,147,483,552 >> 4)将它移到右边的4个位置会给我们:)

11111000 00000000 00000000 00000110

or the number -134,217,722.

(或者数字为-134,217,722。)

So we see that we have preserved the sign of our negative numbers by using the arithmetic right shift, rather than the logical right shift.

(因此,我们看到通过使用算术右移而不是逻辑右移,我们保留了负数的符号。)

And once again, we see that we are performing division by powers of 2.

(再一次,我们看到我们正以2的力量进行分裂。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...