编程参考 - C/C++中的左右移位操作

左移右移位运算符

Left shift and right shift operators (<< and >>)

位移运算符是右移运算符(>>),它将整数或枚举类型表达式的位移到右边,左移运算符(<<),它将位移到左边。

The bitwise shift operators are the right-shift operator (>>), which moves the bits of an integer or enumeration type expression to the right, and the left-shift operator (<<), which moves the bits to the left.

Syntax

shift-expression:

shift-expression << additive-expression

shift-expression >> additive-expression

对无符号的整数的位移操作:

左移:右边空出的位补零(zero filled),左边移除的位丢弃。

右移:左边空出的位补零,右边移除的位丢弃。

例子:

0x08 >> 1 = 0x04

0x01 << 1 = 0x00

或使用下面代码:

#include

#include

int main(int arc, char** args)

{

   int a, val;

   unsigned int b, valb;

   char* str;

   printf("sizeof(int) is %ld\n", sizeof(int));

   str = args[1];

   printf("The string is: %s\n", str);

   a = strtol(str,(char**)NULL, 16);

   b = strtol(str,(char**)NULL, 16);

   printf("The convert number is: 0x%X\n", a);

   val = a>>1;

   printf("Int value>>1 is 0x%X\n", val);

   val = a<<1;

   printf("Int value<<1 is 0x%X\n", val);

   valb = b>>1;

   printf("Unsigned Int value>>1 is 0x%X\n", valb);

   valb = b<<1;

   printf("Unsigned Int value<<1 is 0x%X\n", valb);

   return 0;

}

$ gcc -o main main.c

$ ./main 0xFFFFFFFF

sizeof(int) is 4

The string is: 0xFFFFFFFF

The convert number is: 0xFFFFFFFF

Int value>>1 is 0xFFFFFFFF

Int value<<1 is 0xFFFFFFFE

Unsigned Int value>>1 is 0x7FFFFFFF

Unsigned Int value<<1 is 0xFFFFFFFE

我的GCC版本:

gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)

可以看到,0xFFFFFFFF左移一位是0xFFFFFFFE,右移一位是0x7FFFFFFF。

对有符号的整数的位移操作:(根据我的编译器进行的测试)

- 左移:

如果是负数,则最高位是1,左移时会保持最高位是1,结果就是负数。

如果是非负数,则正常移位,移位后的结果的正负性,根据最高位来判定。

- 右移:

如果是负数,则最高位是1,右移时空出的位用1补齐。

如果是非负数,则最高位不是1,右移时空出的位用0补齐。

移位和类型提升 / Shifts and promotions

移位操作符和两边的操作数构成了此移位表达式,操作数要求是整数。根据标准转换的规则进行整型类型提升(Standard conversions | Microsoft Docs)。

整个移位表达式的结果的类型,和整型提升后的类型一样。

如下例子所示,char型的变量,类型提升后变成整型:

#include

#include

using namespace std;

int main() {

  char char1 = 'a';

  auto promoted1 = char1 << 1;

  cout << typeid(promoted1).name() << endl;

  auto promoted2 = char1 << 10;

  cout << typeid(promoted2). << endl;

  return 0;

}

这里输出的类型的名字,如果是MSVC编译器,是“int”。

用GCC编译器,输出是“i”。

细节

E1 << E2 中,如果E2是负的,则此移位操作的结果是未定义的。

如果E2大于或等于移位表达式的位数,同样也是未定义的。

如果E2为0,则不进行移位操作。

备注 Footnotes

以下是C++11 ISO规范(INCITS/ISO/IEC 14882-2011[2012])第5.8.2和5.8.3节中对移位操作符的描述。

E1 << E2的值是E1左移了E2数量的位;空出的位被填为零。如果E1是无符号类型,结果的值是E1×2^E2,如果值溢出,要对此结果的类型可表示的最大值加1后取模。如果E1是有符号类型和非负值,并且E1×2^E2可以在结果类型的相应无符号类型中表示,那么该值转换为结果类型后,就是该值;否则,行为未定义。

E1>>E2的值是E1右移了E2数量的位。如果E1是无符号类型,或者E1是有符号类型和非负值,结果值是E1/2^E2商的整数部分。如果E1是有符号类型且为负值,那么结果值是根据实现定义的。


The following is the description of the shift operators in the C++11 ISO specification (INCITS/ISO/IEC 14882-2011[2012]), sections 5.8.2 and 5.8.3.

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1 × 2E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.


参考:

Left shift and right shift operators ('<>') | Microsoft Docs

你可能感兴趣的:(编程,c语言,c++)