为什么此人使用(1 << 0)?

时间:2019-09-09 10:30:10

标签: c

我正在阅读有关函数实现的代码,编写该代码的人将其写在他的.h中:

#define FT_LS_LONG      (1 << 0)
#define FT_LS_RECURSIVE (1 << 1)
#define FT_LS_HIDDEN    (1 << 2)
#define FT_LS_REVERSE   (1 << 3)
#define FT_LS_TIME      (1 << 4)
#define FT_LS_LINE      (1 << 5)

为什么他使用按位左移而不是其他? 而且,他本可以用什么替换这部分代码? 我知道 (1 << 0)== 0000 0001 (1 << 1)== 0000 0010,依此类推。 但是我不知道如何使用它们。

5 个答案:

答案 0 :(得分:3)

这些构造通常用于组合成单个单词的标志中。可以使用按位或运算符将它们合并,例如:

int flags = FT_LS_LONG | FT_LS_HIDDEN;

在上面的代码中,flags变量将设置为0000 0101。 然后可以使用按位AND运算符来测试flags变量,例如:

if (flags & FT_LS_LONG) { foo(); }

if语句的值为true,并且将调用foo()函数。

if (flags & FT_LS_TIME) { bar(); }

if语句的计算结果为false,并且不会调用bar()函数。

答案 1 :(得分:3)

它是自记录代码。 1可能有任何含义,而1 << 0绝对是位掩码。请注意,由于移位是整数常量表达式,因此在编译时对其进行求值。

更多的代码格式化将使其变得更加整洁:

#define FT_LS_LONG      (1 << 0)
#define FT_LS_RECURSIVE (1 << 1)
#define FT_LS_HIDDEN    (1 << 2)
#define FT_LS_REVERSE   (1 << 3)
#define FT_LS_TIME      (1 << 4)
#define FT_LS_LINE      (1 << 5)

毫无疑问,这些是用于屏蔽来自同一字节的不同数据位的位屏蔽。

也可以使用十六进制文字编写等效代码,这只是样式问题:

#define FT_LS_LONG      0x01u
#define FT_LS_RECURSIVE 0x02u
#define FT_LS_HIDDEN    0x04u
#define FT_LS_REVERSE   0x08u
#define FT_LS_TIME      0x10u
#define FT_LS_LINE      0x20u

答案 2 :(得分:2)

他可能已经做到了,因为它更加清晰。 FT_LS_LONG由第一(第零)位表示。他还可以将其保留为# define FT_LS_LONG 1,但由于所有这些宏都包含在单个字节中,因此不清楚。

答案 3 :(得分:-1)

不看原始代码很难说,但这似乎是以可读的方式定义标志的。替代方法是使用#defines设置为0000001,0000010,0000100等。它的可读性较差且容易出错(如果错过0或1,将很难判断程序在哪里失败)

在实现中,我希望能看到按位排列,并且试图找出哪个标志是打开还是关闭。

答案 4 :(得分:-1)

正如其他答案所暗示的,这通常是由于使用标志引起的,但这不一定是唯一的原因。

例如,对于微控制器而言,地址空间非常宝贵,因此它们将多个属性打包在一个字节中,有时它们只是布尔标志,有时它们可​​能是其他东西,例如时钟分频因子,并且可能由几位组成,但是由于地址空间极为有限,因此它与其他标志和/或值存储在同一外围设备配置寄存器中,因此它们可能是例如从位2开始的5位,并且您可能会发现诸如0b10101 << 2或以0x15 << 2十六进制表示。

在微控制器的情况下,可以更轻松地在文档中查找,只需查看寄存器及其中的哪个位...因为您不必在二进制表示中计数0或将其转换为十六进制甚至更差的十进制来找出相应的值。