深刻懂得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
二. 移位運算符
左移運算符是把操作數的值的每位向左挪動,挪動的位數有左邊的操作數決議,右邊空出的位數用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
右移運算符是把操作數的值的每位向右挪動,挪動的位數有左邊的操作數決議,右邊拋棄的位數用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++移位運算符就是小編分享給年夜家的全體內容了,願望能給年夜家一個參考,也願望年夜家多多支撐。