使用 1 按位设置一个字节的所有位

Using 1 to bitwise set all bits of a byte

我目前像这样将值硬编码为 255

uint8_t outStates       = 0xFF;

但我有一个使用起来更干净的宏

#define TCA9555_LOW (1)

我唯一能想到的就是这种方式,但它看起来效率低下而且读起来更难看,这不是我想要的

for(int i = 0; i < 8; i++)
{
    outStates |= (TCA9555_LOW << i);
}

是否有更漂亮的方法来一次设置所有位,使用易于阅读的值为 1 的宏?

非常感谢!!

您想在不循环的情况下将每个位设置为 TCA9555_LOW 的值。为此,您可以使用以下方法:

uint8_t outStates =
     ( TCA9555_LOW << 7 )
   | ( TCA9555_LOW << 6 )
   | ( TCA9555_LOW << 5 )
   | ( TCA9555_LOW << 4 )
   | ( TCA9555_LOW << 3 )
   | ( TCA9555_LOW << 2 )
   | ( TCA9555_LOW << 1 )
   | ( TCA9555_LOW << 0 );

但如果我们仔细想想,只有两种可能的结果。以下是等效的:

uint8_t outStates = TCA9555_LOW ? 0xFF : 0x00;

最后,在同样的基础上,我们可以使用如下:

uint8_t outStates = 0;
if (TCA9555_LOW)
   outStates = ~outStates;

在前两种情况下,编译器应该将表达式折叠成一个常量。甚至第三个。

这个:

#define TCA9555_LOW (1)
/* if TCA9555_LOW is set, we use active-low logic, 
   so default to all eight bits set */
#define TCA9555_DEFAULT (TCA9555_LOW ? 0xff : 0)

...

uint8_t outStates = TCA9555_DEFAULT;

不要让它太难。如果你像我感觉到的那样在做低级位摆弄,那么当你说“这八位需要在这里是一个”时,每个人都会理解它,并且 0xff 是一种明确的方式按原样呈现。 (如果它是 21 位,我可能会使用 (1 << 21) - 1,而不是 0x1fffff,只是为了避免 reader 计算数字,但即使没有它,一个完整的字节也是清晰的。)

设置为-1

C 标准说:

6.3.1.3 Signed and unsigned integers

When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

因此将 uint8_t 设置为 -1 实际上会设置 UINT8_MAX + 1 - 1 什么是 255。此方法适用于所有无符号类型。

将所有位设置为一个是一种简单、便携、方便的方法。