代码之家  ›  专栏  ›  技术社区  ›  pmoubed

为什么这个移位操作加上按位运算只能在31位之前工作?

  •  -2
  • pmoubed  · 技术社区  · 4 年前

    为什么下面的移位操作会起作用,结果是相等的? 这个图案有名字吗? 我正试图找出写这段代码的人脑子里到底发生了什么!

    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;
        }
    }
    

    使现代化

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

    2 回复  |  直到 4 年前
        1
  •  2
  •   eerorika    4 年前

    这个图案有名字吗?

    0x1u << pos (或者只是 1u << pos )是一种模式,用于获取只有位的数字 pos 一切就绪。使用签名 0x1 通常是反模式的。

    i |= 1u << pos 是一种设置位的模式 销售时点情报系统 整数的 i .

    (1u << pos) - 1 是一种仅在小于的位置创建设定位模式的模式 销售时点情报系统 .

    为什么下面的移位操作会起作用,结果是相等的?

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

                         // 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
    

    最多只能工作到31岁

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

        2
  •  2
  •   Vlad Feinstein    4 年前

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

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

    例子:

    如果 J 是3, j+1 4岁, 1. 移位4就是 0b1000 ; 减去1,得到 0b0111

    关于 Is there any name for this pattern? -我看了 here ,此模式使用了几次,但未命名。可能太明显了:)