按位或与添加标志


16

我见过其他人以前使用位或来组合标志:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN | JUMP | SHOOT;

我也是这么做的。

但是我也看到了使用加法的一些(不是很多)组合标志:

#define RUN 0x01
#define JUMP 0x02
#define SHOOT 0x04

const byte madPerson = RUN + JUMP + SHOOT;

哪一个更“可读”?(您认为更多人会认出哪个?)这样做的“标准”方法是什么?你更倾向哪个?


这是一个SO问题。请考虑使用像1<<01<<11<<2,等等。当您有许多标志时,它变得更易读,更可维护且不易出错。例如,如果您要打包一个64位int的所有64位,那么您真的想避免输入错误:)表示1方式也很重要。对于VS2010中的64位整数,我认为它是1UI64或类似的东西。使用错误的类型可能会咬你。
Job

3
@Job:不是StackOverflow问题,因为它询问的是可读性,可识别性,首选项和最佳实践。没有一个客观的答案。它属于这里。
Macneil 2010年

Answers:


34

按位或。

加法很危险。

考虑一个例子,其中一个匪徒是一个人,而一个愤怒的匪徒是一个说话并射击的匪徒。稍后,您确定所有匪徒都应该射击,但是您已经忘记了愤怒的匪徒定义,并且不要删除其射击标志。

#define PERSON 1 << 0
#define SPEAKS 1 << 1
#define SHOOTS 1 << 2
#define INVINCIBLE 1 << 3
const byte bandit = PERSON | SHOOTS;                    // 00000101
const byte angryBandit_add = bandit + SPEAKS + SHOOTS;  // 00001011 error
const byte angryBandit_or = bandit | SPEAKS | SHOOTS;   // 00000111 ok

如果你用过 angryBandit_add游戏,现在会遇到令人迷惑的逻辑错误,那就是拥有无法射击或被杀死的愤怒的土匪。

如果您使用angryBandit_or了最糟糕的情况,那将是多余的| SHOOTS

出于类似的原因,按位NOT的安全性要好于删除标志的减法。


11

按位或运算可以更清楚地传达意图

同样,按位或运算应该更有效


+1的确确实是我也认为OR可以更清楚地表明这些是标志,但是考虑到效率,有些语言的按位运算速度很慢,例如JavaScript所有Numbers为64个浮点数,按位运算符需要对它们进行隐式转换。
Ivo Wetzel 2010年

1
给定OP的示例,我认为一行OR或加法不会对程序的执行速度产生不利影响。
Tin Man 2010年

1
@Greg:尤其是因为该示例中的计算将在编译时完成。:-)
Carson63000 '12

除了传达意图之外,在许多语言中看到这种现象也很普遍,包括但不限于ADA,C#,Java ...
Ken Henderson 2010年

2
“应该”在这个行业中是一个非常重要的词。尽管您今天不太可能遇到此问题,但是我对使用没有按位或指令的处理器的工作记忆非常清晰。您可以在一条指令中进行按位与运算,也可以在一条指令中进行按位异或运算,但是按位异或运算需要两个指令:立即按位与运算关闭该位,以及立即按位异或运算以补充新清除的位。 ,当然可以设置。
John R. Strohm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.