为什么这个移位操作加上按位只能工作到 31?

Why this shift operation plus bitwise works only up to 31?

为什么下面的移位运算有效并最终相等? 这种模式有什么名字吗? 我想知道写这段代码的人脑子里到底在想什么!

int i = 0x1;
i |= 0x1 << 1;
i |= 0x1 << 2;
i |= 0x1 << 3;
i |= 0x1 << 4;
i |= 0x1 << 5;

int j = 5;

if( ((0x1 << (j + 1)) - 1) == i)
{
    // WHY?
}

我试图检查这是否适用于所有数字,但只适用于 31。

for (int i = 1; i <= 100; i++) {
    int total_1 = 0x1;
    for (int j = 1; j <= i; j++) {
        total_1 |= 0x1 << j;
    }

    int total_2 = (0x1 << (i + 1)) - 1;
    if (total_2 == total_1) {
    } else {
        cout << i << endl;
        break;
    }
}

更新

请解释第一部分为什么它们最终会相等?

UPDATE Please explain the first part why they would end up equal?

((0x1 << (j + 1)) - 1)j 低位设置为 1

示例:

j为3,j+1为4,1平移4为0b1000;减去 1 - 你得到 0b0111

回复:Is there any name for this pattern? - 我看过 here,这个模式用过几次,但没有命名。可能太明显了:)

Is there any name for this pattern?

0x1u << pos(或 1u << pos)是一种获取数字的模式,仅设置位置 pos 中的位。使用带符号的 0x1 通常是 anti-pattern.

i |= 1u << pos 是一种模式,用于在整数 i.

的位置 pos 设置一个位

(1u << pos) - 1 是一种模式,用于创建仅在小于 pos.

的位置设置位的模式

Why shift operation below works and end up equal?

也许查看中间结果可能会有所帮助:

                     // least significant byte
int i = 0x1;         // 0b0000'0001
i |= 0x1 << 1;       // 0b0000'0011
i |= 0x1 << 2;       // 0b0000'0111
i |= 0x1 << 3;       // 0b0000'1111
i |= 0x1 << 4;       // 0b0001'1111
i |= 0x1 << 5;       // 0b0011'1111

int      j = 5;
 0x1 << (j + 1)
 0x1 <<    6         // 0b0100'0000
(0x1 << (j + 1)) - 1 
 0b0100'0000     - 1 // 0b0011'1111

only works up to 31

int 在您的系统上可能是 32 位宽。如果将 32 位 0x1 左移 31 位或更多位,则程序的行为是未定义的。如果你要使用0x1u,那么你可以移动31,但32及以上将是UB。