之前收藏過一篇講C++位操做的文章,此次博客搬家,之前的數據都沒有保留,整理谷歌網站管理後臺的時候,發現不時的還有網友有在查找這篇文章。因此,瘋刀也來弄個簡單的教程,講講位操做的用途和魅力吧。網絡
位是數據存儲的最小單位。在 計算機中的二進制數系統中,位,簡記爲b,也稱爲比特,每一個0或1就是一個位(bit)。網站
咱們先來看看位運算操做符:& (按位與)、| (按位或)、^ (按位異或)、~ (按位取反)、>> (按位右移)、<< (按位左移)。spa
一、&(按位與) 從概念上來說,就是將參與運算的兩個份量對應的每一位來作邏輯與運算,若二者都爲真(等於1),則結果才爲真(等於1)。不然都爲假(等於0)。
即:1 & 1 = 1 、1&0 = 0 、0&1 = 一、0&0 = 0
這裏咱們先來看看那一個8位二進制的例子:
7&8 = 0000 0111 & 0000 1000 = 0000 0000 = 0
7&6 = 0000 0111 & 0000 0110 = 0000 0110 = 6教程
二、| (按位或) 即把參與運算的每一個份量對應的每一位來作邏輯或運算,即二者都爲假(爲0)時,才爲假(爲0),不然皆爲真。
即:0|0 = 0、1|0 = 一、0|1 = 一、1|1 = 1
來看看8位二進制的例子:
7|8 = 0000 0111 | 0000 1000 = 0000 1111 = 15
7|6 = 0000 0111 | 0000 0110 = 0000 0111 = 7遊戲
三、^(按位異或) 即把參與運算的每一個份量對應的每一位來作異或運算,即二者相同爲假,不一樣爲真。
即:0|0 = 0、 1|0 = 一、0|1 = 一、 1|1 = 0
看下面的例子:
7^8 = 0000 0111 ^ 0000 1000 = 0000 0111 = 7
7^6 = 0000 0111 ^ 0000 0100 = 0000 0011 = 3遊戲開發
四、~(按位取反) 即把二進制位的每一位進行取反運算,簡而言之就是1變成0,0變成1。
直接看例子:
~7 = ~0000 0111 = 1111 1000 = 248開發
5 >>(按位右移)把二進制位總體向右移動。
7>>1 = 0000 0111 >> 1 = 0000 0011 = 3
7>>2 = 0000 0111 >> 2 = 0000 0001 = 1
這裏右移等於除了2的N次方,N爲右移的位數。get
6 <<(按位左移)這裏就不詳細說了,和右移相反。同步
好了,下面講講實際應用吧。
1、一種顏色的表示方式—- 經過DWORD來表示顏色
定義:typedef unsigned long DWORD;
即爲一個無符號32位(32機器)長整數,有四個字節,咱們從左到右叫他1,2,3,4字節,每個字節的範圍是0~255。第一個字節表示alpha值,即透明度。若是是255,表示不透明,0表示徹底透明(博客
看不到),其餘分別是R,G,B值。
可經過下列方法得到每一個字節的值:
int A = (int)((DWORD & 0xFF000000) >> 24);
int R = (int)((DWORD & 0x00FF0000) >> 16);
int G = (int)((DWORD & 0x0000FF00) >> 8);
int B = (int)(DWORD & 0x000000FF);
DWORD dwColor = (A<<24)+(R<<16)+(G<<8)+B;
有了前面的基礎,我相信你們對上面的換算方法,一看就明白吧。若是對16進制不敏感的童鞋,能夠用計算機把十六進制換算成二進制,更容易理解。
2、狀態系統中的使用
在遊戲開發中,咱們一般用一個32位(假設這裏用32位)的整數來存儲角色的狀態(這樣作主要是爲了節約存儲空間,同時也減少網絡同步消息包的size)。所謂的狀態,就是你們熟悉的Buff或者DeBuff。
enum ROLE_STATUS
{
STATUS_NORMAL = 0, // 正常
STATUS_DIE = 1, // 死亡狀態
STATUS_GOD , // 無敵
STATUS_DISAPPEARING , // 消失中狀態
STATUS_DEF_ADJUST , // 物理防護提高/下降
STATUS_MDEF_ADJUST , // 魔法防護提高/下降
STATUS_ATK_CRI_ADJUST , // 同時提高物理攻擊和爆擊率
STATUS_MAXHP_ADJUST , // HP上限調整
STATUS_MAXMP_ADJUST , // MP上限提高/下降
//……
這裏最多隻能寫32個,由於咱們假設是用32位數據來存儲狀態。
};
狀態數據定義好了,如今來看看怎麼使用他們。
首先, 角色上線,我要給他一個保護狀態,應該這樣操做。
DWORD dwRoleStatus = STATUS_GOD;
同時,角色使用了一個物品,這個物品的效果時,HP和MP上限增長一段時間。所以要附加調整玩家的HP和MP上限的狀態,應該這樣。
DWORD dwRoleStatus |= (STATUS_MAXHP_ADJUST+STATUS_MAXMP_ADJUST);
這裏是|=而不是=操做,由於不能清掉以前附加的無敵保護狀態。因此用或運算。
該角色受到其餘玩家或者怪物的攻擊,咱們要判斷被攻擊的這個角色的受保護狀態狀態還在不在。執行以下邏輯
if( dwRoleStatus & STATUS_GOD ) // 判斷位是否爲1
{
// 受保護狀態,不能被攻擊
}
接下來,角色無敵保護時間過時了,咱們要清除無敵狀態,執行以下操做
dwRoleStatus &= ~STATUS_GOD;
這裏用到了取反的計算。~STATUS_GOD的結果是第二位爲0外,其餘都爲1。而後和dwRoleStatus作按位與計算。
STATUS_GOD 等於 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010;
~STATUS_GOD 等於 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101;
所以和dwRoleStatus相與以後,dwRoleStatus除了第二位之外的位,都保留下來了。第二位不論是什麼值,都會被設置爲0,這樣子就把STATUS_GOD這個狀態清除掉了。同理咱們要清除多個狀態的時候,先把要清楚的狀態或運算到一塊兒。再取反,而後和dwRoleStatus按位與。起到同時清除多個狀態。