用标志位表示状态

在很多框架中, 我们都能看到类似 int xxx = 0x0010 这种代码, 我们只知道他表示状态, 很牛x, 但是具体为啥要这样, 或者它是如何表示多个不同状态的却全然不知.

回顾位运算

位运算符号列表

符号英文名中文名
\OR
&AND
~NOT
^XOR异或
>>-右移
<<-左移
>>>-无符号右移(最高位始终补0)

每种运算符的运算方式

1 | 0   // 1, 两个有一个 1 结果为 1, 其他情况都为 0
1 & 0   // 0 两个都为 1 结果为 1, 其他情况都为 0
~ 1     // 0 单目运算, 取运算值的反值
1 ^ 0   // 1 参与运算的两个值不同, 则为 1, 相同则为 0
1 << 1  // 10 将左边的值 左移 指定位数
1010 >> 1   // 101 将左边值 右移 指定位数
标志位: 将一个整数的某一位作为标志位, 并赋予特定的含义

假如我们要保存一个用户的增删查改权限, 四种权限组合, 一共有 16 中状态.

public static int NONE      = 0;
public static int ADD       = 1;
public static int DELETE    = 2;
public static int READ      = 4;
public static int UPDATE    = 8;

我们通过这几种值表示是否在某个方向,为什么要用这些特定的值?

1   =   0001
2   =   0010
4   =   0100
8   =   1000

这些值都是 2 的次幂, 将这些值转换为二进制, 发现每个值有一个位是 1 其他都是 0, 并且相同位不重复

这样, 每个状态参与位运算始终只影响该转态位的值

再定义一个表示权限的标识 permission, 默认是无任何权限

假如需要添加 READ, ADD 权限

permission |= ADD | READ;
//  0 | 0001 | 0100 = 0101
/**
0000
0001
0100
----
0101
*/

我们添加了两个权限, 分别是 ADD , READ, 则这两个标志位的的值变成了 1

如何检查是否拥有某个权限

boolean canRead = (permission & READ) != 0
// 0101 & 0100 = 0100 = ADD
/**
0101
0100
----
0100
*/

如何移除某个权限

permission ^= READ
// 0101 ^ 0100 =  0001
/**
0101
0100
----
0001
*/

另一方式移除某个权限

permission &= ~ READ
// 0101 & 1011 = 0001
/**
 ~0100
  ----
  1011
 &0101
  ----
  0001
*/
标志位的优势

标志位可以减少很多代码, 理解简单

如果我们用一个 boolean 给一个对象添加 READ 和 ADD 权限

setCanRead(true);
setCanAdd(true);
setCanUpdate(false);
setCanDelete(false);

用标志位

addPermission(READ | ADD);

用 boolean 判断是否拥有 READ 和 ADD 权限

isCanRead();
isCanAdd();

用标志位

hasPermission(ADD | READ);

用 boolean 判断是否拥只有 READ 和 ADD 权限

isCanAdd() isCanRead && !isCanUpdate() && !isCanDelete()

用标志位

isJustAllow(READ | ADD);

上例中的代码

class Permission {
    public static final int NONE        = 0;
    public static final int ADD         = 1;
    public static final int DELETE      = 2;
    public static final int READ        = 4;
    public static final int UPDATE      = 8;

    private int mPermission = NONE;

    public void addPermission(int permission){
        mPermission |= permission;
    }
    public boolean hasPermission(int permission){
        return  (mPermission & permission) != NONE;
    }
    public boolean isJustAllow(int permission){
        return mPermission == permission;
    }
    public void removePermission(int permission){
        mPermission ^= permission;
    }
}

转自:https://www.denua.cn/blog/article/26/

### LabVIEW 中状态标志位的使用方法 #### 定义与作用 状态标志位在LabVIEW中用于控制程序流程,通常是一个布尔变量或枚举类型的数值。这类标志位能够指示特定条件是否满足,从而影响后续操作的行为[^1]。 #### 创建与设置 为了创建一个有效的状态标志位,在前面板上放置一个布尔控件(如开关),并将其连接到对应的程序逻辑部分。当需要改变该标志的状态时,可以通过VI脚本中的相应节点来完成这一动作。例如,利用`While Loop`内的条件判断语句配合Shift寄存器传递前一次迭代的结果给下一轮循环作为输入参数之一,以此达到持续更新目的的效果[^3]。 #### 应用场景举例 假设有一个简单的温度监控系统,其中包含了一个用来检测当前环境温度是否超过预设阈值的状态标志位。一旦触发高温警报,则会激活一系列响应措施直至恢复正常工作范围为止。此时就可以借助于上述提到的方法构建起完整的反馈机制: ```labview // 假定此为伪代码表示形式而非实际LabVIEW语法 while (true){ float currentTemp = readTemperatureSensor(); // 获取实时温度数据 bool isOverheated = checkIfOverheat(currentTemp); // 判断是否过热 shiftRegister(isOverheated, &previousState); // 将本次结果传送给下次循环使用 if(previousState && !isOverheated){ // 如果之前处于报警状态而现在已恢复常态... sendNotification("System back to normal"); // 发送通知告知用户情况好转 }elseif(!previousState && isOverheated){ // 若是由正常转为异常则启动应急方案.. activateEmergencyProtocol(); } } ``` #### 解决常见问题 对于可能出现的问题及其解决方案如下: - **无法正确反映最新状态**:确保每次修改后的值都被及时保存下来供下一个周期读取;检查是否有其他地方意外更改了这个共享资源。 - **性能瓶颈**:如果频繁查询某个复杂计算得出的结果可能会拖慢整个应用程序的速度,考虑采用缓存策略减少重复运算次数。 - **同步失败**:多线程环境下要注意防止竞争条件的发生,即两个以上进程试图同时访问同一份数据而导致不一致现象。可以引入互斥锁等手段加以保护。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值