c++位运算运用之掩码(BitMask)

c++位运算运用之位掩码(BitMask)

场景:假如我想写一个动画小人,某个接口仅仅传int型就可以同时控制小人抬右手、抬左脚、闭眼睛,或者同时抬右手,抬左脚、睁眼睛。这儿其实就是一些动作的组合,可以把不同动作对应到int的每一个位上,int 占4个字节,每个字节8位,共32位,每一个位来表示一种动作,那么可以同时组合32个动作。
内存分布就像这样:
11111111 11111111 11111111 11111111
这样一个int 的值就是INT_MAX
实现:
1.定义枚举表示各种动作:

enum Animation {
    None = 0,                 // 0x0
    ShutEye = 1 << 1,         // 0x1
    OpenEye = 1 << 2,         // 0x10
    RaiseRightLeg = 1 << 3,   // 0x100
    RaiseLeftLeg = 1 << 4,    // 0x1000
    RaiseRightHand = 1 << 5,  // 0x10000
    raiseLeftHand =1 << 6     // 0x100000
};

1.定义方法实现不同动作组合:

void Dance(int animation)
{
    switch (animation)
    {
    case (ShutEye | RaiseLeftLeg | RaiseRightHand):
        std::cout << "小人 举右手 、 抬左腿、 闭眼" << std::endl;
        break;
    case (OpenEye | RaiseLeftLeg | RaiseRightHand):
        std::cout << "小人 举右手 、 抬左腿、 睁眼" << std::endl;
        break;
    default:
        break;
    }
}

int main()
{
    Dance(ShutEye | RaiseLeftLeg | RaiseRightHand);
    std::cout << "Hello World!\n";
}

哈哈哈,脑补一下画面就好,为了说明问题就使用简单的文字说明,如果真得有人个小人在画面上起舞,那将输出行换成相应的实现逻辑即可。

掩码的常用操作:
1.组合不同的标志位,直接使用位运算或(|)起来,就如我想让小人抬左脚和抬右脚 :
RaiseLeftLeg | RaiseRightLeg
或运算
2.去掉flag中的某一项,就比如我们永远都不想让小人抬起右脚。这时可以分两步走,第一步把要去掉的标志位取反。第二步在和目标标志位与(&)起来。

取反 在与

那么现在我只想小人的眼睛永远是睁开的,闭着就不美了,怎么办呢? 只需去掉标志ShutEye即可

void Dance(int animation)
{
    int noShutEye = ~Animation::ShutEye; // 1. 取反
    animation = animation & noShutEye;   // 2. 与目标值&起来
    // 将上面合并为一行
    // animation = animation & (~Animation::ShutEye);
    switch (animation)
    {
    case (ShutEye | RaiseLeftLeg | RaiseRightHand):
        std::cout << "小人 举右手 、 抬左腿、 闭眼" << std::endl;
        break;
    case (OpenEye | RaiseLeftLeg | RaiseRightHand):
        std::cout << "小人 举右手 、 抬左腿、 睁眼" << std::endl;
        break;
    default:
        break;
    }
}

总结:
位掩码在编码中还是比较常见的,其中要注意的一点就是一个int 仅仅可以表示32种标志,因为只有32位二进制,并且用1标识哪一个位代表什么flag。如果还需要多余32中可以挑一个更大的类型,或者直接使用自定义类,实现与或取反(& | ~)三种操作符,那么即可扩展到好多标志。还有就是去掉标志位时,一定要先取反在与。得呢,今也差不多了,早早就起来撸文章,搞得睡眼朦胧的呢,这可爱的床,我来了。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值