使用位移定义的宏值

时间:2018-05-24 10:35:18

标签: c++ c enums macros bit-shift

我一直在经历一个旧的源项目,试图让它编译并运行(这是一个已经上传到GitHub的旧游戏)。我认为很多代码都是用C风格/ C语法编写的(很多typedef struct {...}等等)我已经注​​意到他们用以下样式定义了某些宏:

#define MyMacroOne (1<<0) //This equals 1
#define MyMacroTwo (1<<1) //This equals 2, etc.

所以我现在的问题是 - 有没有理由为什么会以这种方式定义宏?因为,例如,0x01和0x02是上述数值结果。或者是系统不会读取MyMacroOne = 0x01而是读取具有值(1 <&lt; 0)的“移位对象”?

编辑:感谢您的所有投入!

5 个答案:

答案 0 :(得分:2)

它使定义位值更加直观且不易出错,特别是在多位位域上。例如,比较

#define POWER_ON     (1u << 0)
#define LIGHT_ON     (1u << 1)
#define MOTOR_ON     (1u << 2)
#define SPEED_STOP   (0u << 3)
#define SPEED_SLOW   (1u << 3)
#define SPEED_FAST   (2u << 3)
#define SPEED_FULL   (3u << 3)
#define LOCK_ON      (1u << 5)

#define POWER_ON     0x01
#define LIGHT_ON     0x02
#define MOTOR_ON     0x04
#define SPEED_STOP   0x00
#define SPEED_SLOW   0x08
#define SPEED_FAST   0x10
#define SPEED_FULL   0x18
#define LOCK_ON      0x20

答案 1 :(得分:1)

对人类来说很方便

例如

#define PIN0 (1u<<0)
#define PIN5 (1u<<5)

#define PIN0MASK (~(1u<<0))
#define PIN5MASK (~(1u<<5))

并且很容易看出是否有正确的位位置。它不会使代码变慢,因为它是在编译时计算的

答案 2 :(得分:0)

宏只是替换文字。 Everywhere宏被替换文本取代!!这很方便,特别是如果你想命名一些常常容易出错的东西。

答案 3 :(得分:0)

你总是可以使用常量整数表达式移位来表示(2的)幂的倍数,即Multiple*(2 to the N-th power) = Mutliple << N(有一些警告与你达到整数类型和UB集的保证大小限制时有关在*)并且几乎依赖于编译器折叠它们。

由整数常量组成的整数表达式定义为integer constant expression。这些可以用来指定数组大小,大小写标签和类似的东西,所以每个编译器都必须能够将它们折叠成一个单独的中间体,并且即使它不是这样,它也不会利用这种能力是愚蠢的。严格要求。

*例如:您可以执行1U<<15,但是在16岁时您应该至少切换到1L<<16,因为ints / unsigneds只需要至少有16位和leftshifting整数by its width or into the place where its sign bit is is undefined (6.5.7p4)

  

E1的结果&lt;&lt; E2是E1左移E2位位置;腾空   位用零填充。如果E1具有无符号类型,则值为   结果是E1 x 2E2,比最大值减少了一个模数   值可在结果类型中表示。如果E1有签名类型和   非负值,E1 x 2E2可在结果类型中表示,   那就是结果价值;否则,行为是   未定义。

答案 4 :(得分:0)

为说明此(1<<0)语法的实用性,请考虑Git 2.25(Q1 2020)代码库中的示例,该示例将一组位掩码常量的定义从0ctal文字移到{{1 }}符号。

请参见commit 8679577Hariom Verma (harry-hov)(2019年10月17日)。
(由Junio C Hamano -- gitster --commit 8f40d89中合并,2019年11月10日)

  

builtin/blame.c:常量为位移格式

     

签名人:Hariom Verma

     

我们正在研究位域常数,​​在Git源代码中的其他地方,这种情况是通过移位运算符而不是八进制数来处理的,这也使查找范围内的孔变得更容易

     

如果(1U<<count)丢失:

     
      
  • 更容易在1<<51<<4之间找到它
  •   
  • 这是为了发现1<<6040之间缺少的020
  •   

所以代替:

0100

您得到:

#define OUTPUT_ANNOTATE_COMPAT  001
#define OUTPUT_LONG_OBJECT_NAME 002
#define OUTPUT_RAW_TIMESTAMP    004
#define OUTPUT_PORCELAIN        010