在#define中使用移位运算符的优点
Advantage of using shift operator in #define
在现有代码中,对于某个失败情况有几个"原因"。这些"原因"的定义如下:
#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_FOUND
在STRING_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建议的那样,首选枚举。
- 为什么比较运算符如此快速
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 增量运算符与后缀混淆
- 一个关于在C++中重载布尔运算符的问题
- 运算符C++ "delete []"仅删除 2 个前值
- 模板类无法识别友元运算符
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 关闭||运算符优化
- 通过继承类使用来自不同命名空间的运算符
- #define 与运算符一起使用
- 令牌之前缺少二进制运算符 "#" 当 #define 在 #if 内时出错
- C++模运算符,使用 #define 和自己的类进行浮点运算
- 使用或运算符的多个值为#Define常数
- 当定义与运算符有价值时,#define 如何在编程中工作
- 我可以在define中使用三元运算符吗?反对使用if
- 我可以使用define调用运算符<<
- 在#define中使用移位运算符的优点
- 添加新运算符或类型时 #define 不是可识别的运算符或类型