1、与
将某一位置为0,可以使用与。将该位与'0'进行与操作,其他位与'1'进行与操作。
例如:
bits:0111 1010,我希望把第3位和第1位都置于0,则把(0111 1010)和(1111 0101)进行与操作。
(0111 1010 )& (1111 0101) = 0111 0000
2、或
将某一位直为1,可以使用或。将该位与'1'进行或操作,将其他位与'0'进行或操作。
例如:
bits:0111 1010,我希望把第2位和第0位都置于1,则把(0111 1010)和(0000 0101)进行或操作。
(0111 1010)|(0000 0101)= 0111 1111
3、异或
4、状态位
利用二进制来表示多种状态集合,灵活的组合多种状态。
示例1:
某支付系统中,订单的状态主要有两种类别,即是否已经支付,是否已经结算。我们用一个整型字段status来表示订单的状态,其中status的二进制位中第0位表示支付状态,第1位表示结算状态。如果已经支付,则status的二进制表示形式为*1;否则为*0。如果已经结算,则status的二进制表示形式为1*;否则为0*。其中*表示另外一个状态位的值。
然后我们定义状态常量(status_i),PAY = 0x01;SETTLE = 0x02;其中PAY的二进制表示为01,SETTLE的二进制表示为10。
通过status和状态常量(status_i)的与操作,即可判断订单状态。status & status_i其结果不为零,表示第i个状态为真。
status & PAY = 0,则表示第0位为'0',即未支付;否则第0位为'1',即已支付。
status & SETTLE = 0,则表示第1位为'1',即已结算;否则第1位为'1',即已结算。
当业务逻辑发生变化,需要添加一种状态类别的时候,我们可以继续利用status剩余的二进制位。ADD_STATUS = 0x04。
#include <iostream> int main() { using namespace std; int status; const int PAY = 0x01; const int SETTLE = 0x02; const int OLD = 0x04; while(cin >> status) { if (status & PAY) { cout << "PAY\t"; } else { cout << "NOT_PAY\t"; } if (status & SETTLE) { cout << "SETTLE\t"; } else { cout << "NOT_SETTLE\t"; } if (status & OLD) { cout << "OLD\n"; } else { cout << "NOT_OLD\n"; } } return 0; }
示例2:
在网络通信中,如果客户端需要把信息更新到服务器,我们可以制定一条更新协议,协议包体的数据结构包含了所有需要被更新的字段。
public class ClientInfo { private int id; private String name; private List<Friend> friends; private List<Order> orders; ..... }
在实际需求中,我们往往频繁的更新部分字段。一种节省通信成本的解决方案是拆分协议,把更新协议拆分为频繁的和非频繁的。另外一种解决方案就是在协议包中添加修改标记状态位。协议包中只包含需要更新的字段,并且把该状态位设置为'1'。
final int FIELD_NONE = 0; final int FIELD_1 = 1; final int FIELD_2 = 2; final int FIELD_3 = 4; final int FIELD_4 = 8; final int FIELD_5 = 16; ...... int flag = 0; // 设置第一个字段 flag |= FIELD_1; // 设置第四个字段 flag |= FIELD_4; packet.setFlag(flag);
在服务器端,只需通过flag与常量状态位进行“与”操作,即可判断是否需要更新该字段。
5、状态位在J2SE中的应用
java.util.regex.Pattern
public final class Pattern implements java.io.Serializable { public static final int UNIX_LINES = 0x01; public static final int CASE_INSENSITIVE = 0x02; public static final int COMMENTS = 0x04; public static final int MULTILINE = 0x08; public static final int LITERAL = 0x10; public static final int DOTALL = 0x20; public static final int UNICODE_CASE = 0x40; public static final int CANON_EQ = 0x80; public static Pattern compile(String regex, int flags) { return new Pattern(regex, flags); } /** * Indicates whether a particular flag is set or not. */ private boolean has(int f) { return (flags & f) != 0; } private void compile() { // Handle canonical equivalences if (has(CANON_EQ) && !has(LITERAL)) { normalize(); } else { normalizedPattern = pattern; } // ....... MORE OTHER CODE } }