我一直在经历一个旧的源项目,试图让它编译并运行(这是一个已经上传到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)的“移位对象”?
编辑:感谢您的所有投入!
答案 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 8679577的Hariom Verma (harry-hov
)(2019年10月17日)。
(由Junio C Hamano -- gitster
--在commit 8f40d89中合并,2019年11月10日)
builtin/blame.c
:常量为位移格式签名人:Hariom Verma
我们正在研究位域常数,在Git源代码中的其他地方,这种情况是通过移位运算符而不是八进制数来处理的,这也使查找范围内的孔变得更容易。
如果
(1U<<count)
丢失:
- 更容易在
1<<5
和1<<4
之间找到它- 这是为了发现
1<<6
和040
之间缺少的020
。
所以代替:
0100
您得到:
#define OUTPUT_ANNOTATE_COMPAT 001
#define OUTPUT_LONG_OBJECT_NAME 002
#define OUTPUT_RAW_TIMESTAMP 004
#define OUTPUT_PORCELAIN 010