位操作的作用
位操作在C语言中不是必须的, 但是熟练使用位操作可以节省内存和提高运行效率. 编译器可能会使用位操作来优化代码, 所以反汇编的代码可以看到很多位操作指令.
常用位运算
位与(&), 0 & 0 = 0, 0 & 1 = 0, 1 & 0 = 0, 1 & 1 = 1;
位或(|), 0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1;
位非(~), ~0 = 1, ~1 = 0;
异或(^), 0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0.
标志位
例子: 假设要用很多布尔标志表示一个人的特征, 是否长头发, 是否结婚等, 通常情况是在结构体中定义很多个布尔变量. 要判断是否全部条件满足的时候, 需要很多个逻辑与, 也就是
if (a && b && c ... ), 这样就需要很多次判断, 效率比较低.
如果用标志位来表示, 判断起来就比较简单了. 可以使用一个int 表示一个人的特征, 一个int通常是32位, 每位表示一个特征, 因此最多可以表示32个特征. 比如用位0表示是否长头发, 位1表示是否结婚, ...
设置和获取某位需要一个掩码mask, 掩码的就是只有要操作的位为1, 其他位都为0的值.
比如要操作值value的位7, 则掩码是 0100 0000, 要操作位6, 掩码是 0010 0000...
生成位n的掩码的表达式为:
mask = (1 << n)
设置位7为1的表达式为:
value |= mask
因为, mask只有位7为1, 0 | 1 = 1, 1 | 1 = 1, 所以可以设置位7为1, 而mask的其他位是0, 0 | 0 = 0, 0 | 1 = 1, 也就是不会影响其他位;
设置位7为0的表达式为,:
value &= ~mask
因为, ~mask只有位7为0, 其他位都为1, 而 0 & 0 = 0, 1 & 0 = 0, 可以设置位7为1, 对于其他位, 0 & 1 = 0, 1 & 1 = 1, 没有影响.
根据布尔值b(b=0或b=1)来设置位7的表达式为:
value = (value & make) | (b << 7)
以上表达式可以推广到多个位, 只需要修改掩码就可以轻松做到.
比如同时设置位7和位1为1, 掩码为 0100 0010, 也就是将位7的掩码和位1的掩码执行 位或得到, 表达式为:
value |= (mask1 | mask7)
同时设置位7和位1为0, 掩码同样是 0100 0010, 表达式为:
value &= ~(mask1 | mask7)
判断多个条件是否满足(多位同时为1)的表达式为:
(value & (mask1 | mask2 | ... | mask)) != 0
其中, mask1, mask2, maskn 是n个条件对应位的掩码. 比如要用位7表示是否长头发, 用位1表示是否结婚, 那么同时长头发与结婚可以用 (value & 0100 0010) != 0 判断.
「艾尔登法环」梅琳娜手办开订 立体手办▪
万代「艾尔登法环」白狼战鬼手办开订 立体手办▪
「夏目友人帐」猫咪老师粘土人开订 立体手办▪
「五等分的新娘∬」中野三玖·白无垢版手办开订 立体手办▪
「海贼王」乌索普Q版手办开订 立体手办▪
良笑社「初音未来」新手办开订 立体手办▪
「黑岩射手DAWN FALL」死亡主宰手办开订 立体手办▪
「盾之勇者成名录」菲洛手办登场 立体手办▪
「魔法少女小圆」美树沙耶香手办开订 立体手办▪
「咒术回战」七海建人粘土人登场 立体手办▪
「五等分的新娘」中野二乃白无垢手办开订 立体手办▪
「为美好的世界献上祝福!」芸芸粘土人开订 立体手办▪
「公主连结 与你重逢」六星可可萝手办开订 立体手办▪
「女神异闻录5」Joker雨宫莲手办开订 立体手办▪
「间谍过家家」约尔・福杰粘土人登场 立体手办▪
「街角魔族 2丁目」吉田优子手办开订 立体手办▪
「火影忍者 疾风传」旗木卡卡西·暗部版粘土人登场 立体手办▪
「佐佐木与宫野」宫野由美粘土人开订 立体手办▪
「盾之勇者成名录」第2季拉芙塔莉雅手办开订 立体手办▪
「咒术回战」两面宿傩Q版坐姿手办开订 立体手办▪
「DATE·A·BULLET」时崎狂三手办开订 立体手办▪
「狂赌之渊××」早乙女芽亚里粘土人开订 立体手办▪
「魔道祖师」魏无羨粘土人开订 立体手办▪
「新·奥特曼」奥特曼手办现已开订 立体手办▪