程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 深刻懂得C++移位運算符

深刻懂得C++移位運算符

編輯:關於C++

深刻懂得C++移位運算符。本站提示廣大學習愛好者:(深刻懂得C++移位運算符)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻懂得C++移位運算符正文


關於邏輯移位、算術移位可拜見迅雷深年夜口試題部門。的一道題。

之前看到C++尺度上說,移位運算符(<<、>>)出界時的行動其實不肯定:

The behavior is undefined if the right operand is negative, orgreater than or equal to the length in bits of the promoted left operand.

我其時也沒有深究過這個成績。頭幾天有個網友來信問起這件事,我才發明,這和IntelCPU的移位運算有關。上面是那位網友的來信和我的答復:

您好!運算符<<作為位操作中的高效的操作,但我碰到一個成績:上面在VC情況下發明一個很不明確的處所,上面標注。

#include <stdio.h>

void main()

{

  unsigned int i,j;

  i=35;

 

  //為何上面兩個左移操作成果紛歧樣?

  j=1<<i; // j為8

  j=1<<35; // j為0

}

不知是哪裡沒有懂得對。

緣由是如許的:i=35;j=1<<i;這兩句在VC沒有做優化的情形下,將被編譯成上面的機械指令:

mov dword ptr [i],23h

mov eax,1

mov ecx,dword ptr [i]

shl eax,cl

mov dword ptr [j],eax

在shl一句中,eax=1,cl=35。而IntelCPU履行shl指令時,會先將cl與31停止and操作,以限制左移的次數小於等於31。由於35 & 31 =3,所以如許的指令相當於將1左移3位,成果是8。

而j=1<<35;一句是常數運算,VC即便不做優化,編譯器也會直接盤算1<<35的成果。VC編譯器發明35年夜於31時,就會直接將成果設置為0。這行代碼編譯發生的機械指令是:

mov dword ptr [j],0

對下面這兩種情形,假如把VC編譯器的優化開關翻開(好比編譯成Release版本),編譯器都邑直接將成果設置為0。

所以,在C/C++說話中,移位操作不要跨越界線,不然,成果是弗成預期的。

http://hovertree.com/menu/cpp/

上面是Intel文檔中關於shl指令限制移位次數的解釋:

The destination operand can be a register or a memory location.The count operand can be an immediate value or register CL. The count is maskedto 5 bits, which limits the count range to 0 to 31. A special opcode encodingis provided for a count of 1.

1.掩碼

就是一串2進制 對目的字段停止位與運算,屏障以後的輸出位。

將源碼與掩碼經由邏輯運算得出新的操作數。個中要用到邏輯運算如OR運算。AND運算。用於如將ASCLL碼中年夜寫字母改作小寫字母。

2.與 或 異或 轉換成補碼運算

3.  用法:掩碼 (&)

4. 用法:翻開位 (|)

5.用法:封閉位 (&~)

6. 用法:轉置位 (^)

7. 將Value的第bit_number地位1       Value |= 1 << bit_number;

8. 將Value的第bit_number地位0       Value &= ~( 1 << bit_number );

9.value & 1 << bit_number 假如該地位已被置為1,則表達式的成果為非零值

C/C ++供給位邏輯運算符和移位運算符。兩者只能用於整形和字符型。位運算符是對每位停止操作而不影響閣下兩位,這有別於慣例運算符(&&|| !)是將全部數停止操作的。

一.    位邏輯運算符

1.    ~ 按位取反

將1變成0,將0變成1

EG:

~(10011010)

(01100101)

注:

VC++編譯器,盤算~10,得出的成果是-11。為何不是5呢

10的二進制表現為1010,按位取反響該為0101,也就是十進制的5,為何會得出-11?

VC是32位編譯器,所以

10 = 00000000 00000000 00000000   00001010

~10 = 11111111 11111111   11111111   11110101 =   -11

可以經由過程掩碼(位與) 與15位與

   15 = 00000000 00000000 00000000   00001111

~10 = 00000000 00000000 00000000   00000101   =   -11

2.    & 按位取與

只要兩個操作數都是1成果才是1,不然為0

10 = 00000000 00000000 00000000   00001010

12 = 00000000 00000000 00000000   00001100

&

8 = 00000000 00000000 00000000   00001000

3.    | 按位取或

兩個操作數隨意率性一名為1成果就是1

10 = 00000000 00000000 00000000   00001010

12 = 00000000 00000000 00000000   00001100

|

14 = 00000000 00000000 00000000   00001110

4.    ^ 按位異或

兩個操作數分歧為1,雷同為0

10 = 00000000 00000000 00000000   00001010

12 = 00000000 00000000 00000000   00001100

^

14 = 00000000 00000000 00000000   00000110

5.    用法:掩碼

掩碼是經由過程&(位與)將某些位設置為開(1),將某些位設置為關(0)。將掩碼0看作不通明,將1看著通明。

EG:

如只顯示第2、三位

107 = 0110 1011

6            = 0000 0110

&

2   = 0000 0010

       

6.    用法:翻開位

翻開位是經由過程 |(位或)翻開一個值的特定位,同時堅持其他位的不變。這是由於和0位或都為0,和1位或都為1。

EG:

如只翻開第2、三位

107 = 0110 1011

6   = 0000 0110

|

111 = 0110 1111

7.    用法:封閉位

封閉某些位

EG:

如封閉第2、三位

107 = 0110 1011

6    = 0000 0110

& ~

105 = 0110 1001

8.    用法:轉置位

假如一名為1則轉置為0,假如一名為1則轉置為0

EG:

如轉置第2、三位

107 = 0110 1011

6    = 0000 0110

^

105 = 0110 1101

       

二.    移位運算符

  1. << 左移
  2. 左移運算符是把操作數的值的每位向左挪動,挪動的位數有左邊的操作數決議,右邊空出的位數用0填充

    EG:

    如轉置第2、三位

    107 = 0110 1011 <<2

    <<

    172 = 1010 1100

          

           在盤算機中因為是32位的

    107 = 0000 0000   0000 0000   0000 0000   0110 1011 <<2

    <<

    428 = 0000 0000   0000 0000   0000 0001   1010 1100

    1. >> 右移
    2. 右移運算符是把操作數的值的每位向右挪動,挪動的位數有左邊的操作數決議,右邊拋棄的位數用0填充

      EG:

      如轉置第2、三位

      107 = 0110 1011 >>2

      >>

      26 = 0001 1010

      1、傳統的C方法位操作:

      1.根本操作:

         應用一個unsigned int變量來作為位容器。

      2.操作符:

      |   按位或操作符:result=exp1|exp2;當exp1和exp2中對應位中至多有一個為1時,result中對應位為1,不然為0。

      &  按位與操作符::result=exp1&exp2;當exp1和exp2中對應位全為1時,result中對應位為1,不然為0。

      ^  按位異或或操作符:result=exp1^exp2;當exp1和exp2中對應位不雷同時,result中對應位為1,不然為0。

      ~  反轉操作符:將位容器中的一切位都反轉,1變成0,0變成1。

      << 按位左移操作符:exp<<n,將容器中一切的位向左移n位,空出的位用0填充。

      >> 按位右移操作符:exp>>n,將容器中一切的位向右移n位,空出的位用0填充。

      |=,&=,^= 分離對應|&^三種操作符的復合操作符。

      3.經常使用操作

         這裡我們假定有一個result的unsigned int變量用來貯存32個先生的成就(經由過程和欠亨過火別用0和1),如許result就有33位(result從右至左,從0開端盤算位數,在這個例子中0位被糟蹋)。

      (a) 將第27位設置為合格(設作1)其他位不變:

         result|=(1<<27) //隨意率性的位值與1作按位或操作其值為1,而與0作按位與操作其值不變

      (b) 將第27位設置成不合格(設為0)。

         result&=~(1<<27) //隨意率性的位值與0作按位與操作其值為0,而與1作按位與操作其值不變

      (c) 反轉第27位的值。

         result^=(1<<27) //隨意率性的位值與1作按位異或操作其值為1,而與0作按位異與操作其值不變

      2、C++中的bitset容器

      1.頭文件:

        #include <bitset>

      2.聲明一個容器:

       (a)聲明一個指定位數的空容器(一切位設為0): bitset<int> bits;

       (b)聲明一個指定位數並將指定的幾個位初始化為響應值的容器: bitset<n> bits(int);

           bitdet<int> bits(string&)

      總結:bitset模板類中類型參數傳遞容器的位數,而結構函數參數經由過程一個int或一個string&值來從右至左初始化容器中的響應值。

      3.bitset的根本用法:

      操作

      功效

      用法

      test(pos)

      pos位能否為1?

      a.test(4)

      any()

      隨意率性位能否為1?

      a.any()

      none()

      能否沒有位為1?

      a.none()

      count()

      值是1的位的小數

      count()

      size()

      位元素的個數

      size()

      [pos]

      拜訪pos位

      a[4]

      flip()

      翻轉一切位

      a.flip()

      flip(pos)

      翻轉pos位

      a.flip(4)

      set()

      將一切地位1

      a.set()

      set(pos)

      將pos地位1

      a.set(4)

      reset()

      將一切地位0

      a.reset()

      reset(pos)

      將pos地位0

      a.reset(4)

      4.bitset與傳統C位操作及字符串的轉換

         可以經由過程to_string()成員將容器轉輸入為一個string字符串,別的還可以用to_long()成員將容器輸入到傳統的用於C作風的位容器中。如:

        unsigned long bits = bits.to_long();

        sting str(bits.to_string());

      以上這篇深刻懂得C++移位運算符就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved