如何`(1U << 1)| (1U << 5)` 不同于 `0x22`?

How `(1U << 1) | (1U << 5)` is different from `0x22`?

谁能解释一下具有相同值 VAL1VAL2 的行为有何不同? 对于第一个 if 语句 VAL1 等于零? 谢谢!

#include <stdio.h>

#define VAL1 (1U << 1) | (1U << 5)
#define VAL2 0x22

int main()
{
    printf("VAL1: %d\r\n", VAL1);
    printf("VAL2: %d\r\n", VAL2);

    if (VAL1 == 0)
    {
        printf("TRUE 1\r\n");
    }

    if (VAL2 == 0)
    {
        printf("TRUE 2\r\n");
    }

    if (VAL1 == VAL2)
    {
        printf("TRUE 3\r\n");
    }
}

输出:

VAL1: 34
VAL2: 34
TRUE 1
TRUE 3

两个数字相同,但是当您的宏在您的条件下扩展时,由于 operator precedence.

,它的行为并不像您预期​​的那样

换句话说,展开后的结果如下:

(1U << 1) | (1U << 5) == 0
// is equivalent to
(1U << 1) | ((1U << 5) == 0)

if (VAL1 == 0)中,宏替换将源代码更改为if ((1U << 1) | (1U << 5) == 0)

if 中的表达式被计算为 (1U << 1) | ((1U << 5) == 0), due to a desire to keep C’s operator precedences consistent with those of the earlier language B.

因此我们有 if ((1U << 1) | ((1U << 5) == 0)),其中 (1U << 1) 的计算结果为 2,((1U << 5) == 0) 的计算结果为 0,导致 if (2 | 0),变为 if (2),所以带有 if 的语句被执行。

习惯上定义一个宏替换,它是一个带括号的表达式,以确保它被分组为一个项目:

#define VAL1 ((1U << 1) | (1U << 5))