按位求反问题 - C (Tiva C TM4C123GXL)

Bitwise Negation Issue - C (Tiva C TM4C123GXL)

在使用 TM4C123GXL 时,我遇到了 运行 一个奇怪的行为,我认为这是编译器造成的。 (TI v20.2.5.LTS) 将按位取反函数与等价运算符结合使用时,编译器似乎没有正确遵循操作顺序。

从本质上讲,您会发现选项 #1 不起作用并且会导致错误,即使它应该是正确的(据我所知)。但是,选项 #2 将起作用并将结果为 true。 (据我所知,这与不必要的变量声明相同)

选项 #1(应该有效,但无效)

    uint8_t foo = 0x40; // 0100 0000
    uint8_t fooinv = 0xBF; // 1011 1111
    uint8_t bar = 0x04; // 0000 0100
    uint8_t barinv = 0xFB; // 1101 1111
    bool valid = true;
    valid = (foo == ~fooinv) && valid;
    valid = (bar == ~barinv) && valid;

选项 #2(额外变量但有效)

    uint8_t foo = 0x40; // 0100 0000
    uint8_t fooinv = 0xBF; // 1011 1111
    uint8_t bar = 0x04; // 0000 0100
    uint8_t barinv = 0xFB; // 1101 1111
    uint8_t temp1 = ~fooinv;
    uint8_t temp2 = ~barinv;
    bool valid = true;
    valid = (foo == temp1) && valid;
    valid = (bar == temp2) && valid;

我怀疑这是因为可能存在某种未解决的数据危险,但我无法确定这里发生了什么。我还没有反汇编编译器创建的代码,但感谢任何帮助。

问题是在这些表达式中

valid = (foo == ~fooinv) && valid;
valid = (bar == ~barinv) && valid;

使用整数提升将这样的操作数 ~fooinv 转换为类型 int。所以实际上你正在处理 value = 0xFFFFFF40.

来自 C 标准(6.5.3.3 一元算术运算符)

4 The result of the ~ operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E.

因此,为了获得预期的结果,您应该这样写

valid = (foo == ( uint8_t  )~fooinv) && valid;
valid = (bar == ( uint8_t  )~barinv) && valid;

~的行为在C 2018 6.5.3.3 4中指定,其中包括:

… The integer promotions are performed on the operand, and the result has the promoted type…

整数提升将 uint8_t 转换为 int。因此,在~fooinv中,fooinv0xBF的值被转换为int。这不会改变价值;它仍然是 0x000000BF,这是相同的值,只是显示了更多位。 (对于这个答案,我将使用 32 位 int,这在当前 C 实现中很常见。)然后执行按位取反得到 0xFFFFFF40。这不同于 foo0x40 的值,因此 foo == ~fooinv 当然会产生假(零)。

如果你想计算 fooinv 的按位求反在 uint8_t 中的结果,你可以简单地转换结果:(uint8_t) ~fooinv。比较 foo == (uint8_t) ~fooinv 为真(一)。