位運算符和位運算

位運算:進行而進製爲的運算

系統軟件常常要處理而進制的問題。
eg:將一個存儲單元中的各二進制位左移或者右移一位,兩個數按位相加等等。

雲算符        含義
&            按位與
|            按位或
^            按位異或
~            取反
<<            左移
>>            右移

運算量只能夠是整型或字符型的數據,不能夠爲實型數據。

1)按位與
同則不變,異則爲0 ;
eg:
     011
(&)101
—————————
     001
即爲:
3&5=1;

用途:
(1)清零
eg:要將一個單元清零,即使其全部而進製爲0,只要找一個二進制數,其中各個位符合以下條件:原來的數中的1的位,相對應的位爲0.然後使二者進行&運算,即可達到清零的目的。
eg:
        00010101
(&)     11101010
___________________
        00000000

(2)取一個數中的某些指定位。
eg:有個整數a(2個字節),想要起其中的低字節,只需要將a與(377)8 進行按位與。
(377)後面的8個位都是1,前面的高字節的位都是0,相與了之後,只保留了低字節的數據。

(3)想要保留哪一個位置的數據,就要在哪一個位置上的數進行&運算,次數在該位取1。
就是上面(2)中的一般性。

2)“按位或”運算符(|)
就是而進製爲上主要有一個是“1”,結果在該位位上就是 1 的結果。
作用就是:具有保留“1”的作用。

3)“異或”運算符(^)——————————> 判斷兩個位置上是否爲“異”,爲“異”就去1,否則爲0;
同則爲0,異則爲1.

應用:
(1)是特定的位翻轉
與所有位上的數都是1 的進行異或的時候,該位上的數據將會翻轉;0——>1; 1——>0 ;

(2)與0相^,保留原值。

(3)交換兩個值,不用臨時變量
eg:
a=3,b=4;
將a、b的值進行交換,可以實現如下:
a = a^b;
b = b^a;
a = a^b;
原理:
a = a^b;
    a= 011
(^) b= 100
————————————
    a= 111 = 7
(^) b= 100    b= b^a;
————————————
    b= 011 = 3
(^) a= 111
————————————
    a= 100 =4
可以實現了轉換

4)“取反”運算符
單目運算符,用來對而進制數按位取反,即爲將0變爲1,1變爲0.
~025是對8進制的25按位求反。 取反之後爲:177752

5)左移運算符(<<)
將一個數的二進制位全部左移若干位
eg: a = a<<2; 將a的二進制數左移2位,右補0.
a = 15,二進制爲:00001111,左移兩位得:00111100,十進制爲:60
(高位左移後,溢出將會捨棄)
左移一位相當於該數*2,2位則爲4

總結:左移n位,將會是原來的數乘以2^n;

6)右移運算符(>>)
a>>2 表示將a的各二進制右移2位,移到右端的低位被捨棄,對無符號的數,高位補0;
eg:a=017時,二進制爲:00001111
a>>2 爲:00000011 捨棄了後面的兩位。

即爲:右移n位,相當於除以2^n位。(無符號的)

有符號的
正數的時候:如果原來的符號爲0(該整數位正),則左邊也是移入0(和上面一樣);
如果符號位原來是1(即爲:負數),則左邊移入0還是1,這個要取決於所用的計算機系統。
有的系統移入0,有的系統移入1. 移入0的稱爲“邏輯右移”;移入1的稱爲“算術右移”

7)位運算賦值運算符
位運算符 與 賦值運算符可以組合稱爲符合賦值運算符,
eg:&= 、|= 、>>= ,<<= ,^=

8)不同長度的數據進行位運算
若是兩個數據的長度不同(eg:long型和int型)進行位運算的時候,系統將會將二者按右端對齊。如果b爲正數,則左側16位補滿0,若b爲負數,做左端的應該補滿1,如果b爲無符號整數型,則左側添滿0。

8)位段(對內存中得信息一般是以字節爲存儲單位)
實際上一個存儲信息不必要用一個或者多個字節,例如:"真"或“假”用0 、1 表示即可。
計算機中用於過程控制、參數檢測或者數據通訊領域時,控制信息往往只是佔有一個字節中的一個或幾個二進制位,常常一個字節中存放多個信息。
即爲:一個字節的每一個位都是可以用來存放信息位的。

如何向一個字節中的一個或幾個二進制位進行賦值和改變它的值呢?
方法(1)
人爲的將一個整型變量data分爲幾個部分。
eg:a ,b,c,d 分別佔2位,6位,4位,4位。如果想將c的值變爲12(假設原來是0)
(1》》將數12左移4位,是1100右邊起第4~7位
(2》》將data與“12<<4”進行“按位或”運算,既可以將c的值變爲12.
如果原來的值不是0,則應該先使它爲0.
下面方法:data &=0177417  (左邊的0表示8進制)
(0177417)8的二進制表示爲:1111111100001111,即使data的第4~7位爲0.
記住上面的字比較麻煩:可以使用
~(15<<4) 這個運算出來就是上面的數字了,其他的很大的數據也是可以使用這個方法來實現的。

方法(2)
c語言中“允許在一個結構體中以位爲單位來指定其成員所佔內存長度”,這種以位爲單位的“位段”或“位域”
。利用爲段可以較少的位數存儲數據。
eg:
struct packed_data{
    unsigned a:2;
    unsigned b:6;
    unsigned c:4;
    unsigned d:4;
    int i;
}data;
其中a,b,c,d 分別佔2位、6位、4位、4位,i位整型,共佔用4個字節。

下面關於位段的定義和引用:
(1)位段成員的類型必須指定位unsigned或int類型
(2)若某一位段要從另一個字開始存放,可以一下定義:
unsigned a:1;
unsigend b:2; 一個單元存儲
unsigned :0;
unsigned c:3; ;另一個單元存儲

ps:本來adb是可以存放在一個存儲單元中的,由於用了長度爲0的位段,其作用使下一位段從下一個存儲單元開始存放。
因此,現在只是將a,b存儲在一個單元中,c另存放在下一個單元。

(3)一個位段必須存儲在一個單元中,不可以跨越兩個單元。(即爲:當前的單元的空間不夠用,就用下一個單元進行存儲)

(4)可以定義無名位段
unsigned a:1;
unsigned  :2;(該空間是無名位段,空間不用)
unsigned b:3;
unsigned c:4;

(5)位段的長度不能夠大於存儲單元的長度,也不能夠定義位段數組。
(6)位段可以用整型格式符輸出。
eg:printf("%d,%d,%d",data.a,data.b,data.c);
當然也是可以使用%u,%0,%x等等格式來定義的。
(7)位段可以在數值表達式中引用,它會被系統自動的轉換爲整型數。













發佈了144 篇原創文章 · 獲贊 11 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章