在#define中使用移位运算符的优点

Advantage of using shift operator in #define

本文关键字:运算符 #define      更新时间:2023-10-16

在现有代码中,对于某个失败情况有几个"原因"。这些"原因"的定义如下:

#define STRING_NOT_FOUND   (1 << 0)
#define STRING_INVALID     (1 << 1)
#define STRING_TOO_LARGE   (1 << 2)
...etc

这些是使用函数setFailureReason(int reason);

设置的

与使用数字相比,在定义这些常量时使用移位操作符的优势是什么?

#define STRING_NOT_FOUND   1
#define STRING_INVALID     2
#define STRING_TOO_LARGE   4

当你得到1 << 24或类似的东西时,它变得更有用,大多数人不知道是16777216。

在这种特殊情况下,我不确定为什么它是一个"位域"在所有-它可以是STING_NOT_FOUNDSTRING_INVALID和/或STRING_TOO_LARGE的同时。

和适当的c++将使用enum(即使在C中,这将是首选)。

这主要用于错误码表示一个位域,该位域的值可以被逻辑标记(VALUE_A | VALUE_B)。

使用移位操作符可以提高可读性,并防止有人使用现有的位组合(例如5)插入新的错误代码。

可能是错误的:

#define STRING_NOT_FOUND    1
#define STRING_INVALID      2
#define STRING_TOO_LARGE    4
#define STRING_SOMETHING_KO 5

可能更好:

#define STRING_NOT_FOUND    (1 << 0)
#define STRING_INVALID      (1 << 1)
#define STRING_TOO_LARGE    (1 << 2)
#define STRING_SOMETHING_KO (1 << 3)

使用" 2的幂"只有在查看标志时才真正有意义,其中0..N可能是组合的。每个常量(或枚举值)代表一个特定的被设置为结果十进制数。

首先,一旦你超过了一定的点,你就必须开始做数学运算,"2的幂"写成小数就变得笨拙了。(对我来说,这是8192 x 2。; -))

例如,硬件文档可能会声明"设置寄存器的#4和#8位"。考虑:
// set bit #4 and #8
reg |= 272;

或:

// set bit #4 and #8
reg |= 0x110;
:相比

// set bit #4 and #8
reg |= ( ( 1 << 4 ) | ( 1 << 8 ) )

明显的区别是,使用上述运算符,您将获得自然序列(0,1,2,3,4,5,…)与下一个2的幂(1,2,4,8,16,32,…)相比。第一个更短(log10 n vs log10 2^n),可以说更容易理解。

DevSolar还提出了一个非常重要的观点,即知道比特的数量;我个人记得2到16的所有幂,所以我从来没有真正想过它。

还请注意,在c++中,首选const或constexpr变量,或者如Mats建议的那样,首选枚举。