【问题标题】:Trying to perform bitwise operation on a negative number to make 0s in bits 31-16 (32 bit number) in C尝试对负数执行按位运算以在 C 中的第 31-16 位(32 位数)中生成 0
【发布时间】:2021-09-13 00:20:22
【问题描述】:

我有一个数字 -3,我想将其用作 16 位整数并使用 | (或)具有 32 位整数的运算符。 所以理想情况下,我需要它,以便在二进制二进制补码中 -3 将是 0000 0000 0000 0000 1111 1111 1111 1101 我已经尝试过使用

int x = -3;
x = x << 16;
x = x >> 16;

我认为理想情况下这会将 0 放在 31-16 位(0 索引)中,但它似乎不起作用。任何帮助实现这一点将不胜感激。

【问题讨论】:

  • 是否必须使用shift?也可以使用位掩码:x = x &amp; 0x0000ffff;
  • 如果你想要0000 0000 0000 0000 1111 1111 1111 1101,你为什么不直接使用0xFFFD

标签: c bit-shift twos-complement


【解决方案1】:

在 16 位中获得 3 的补码的两种方法是:

  • 包括&lt;stdint.h&gt; 并使用(uint16_t) -3
  • 使用-3u &amp; 0xffffu

【讨论】:

    【解决方案2】:

    将负值向左移动是未定义的行为

    int x = -3;
    x = x << 16; // UB!
    

    将负值向右移动是实现定义的行为


    移位时最好使用无符号类型(或小的正值)。


    对负数执行按位运算,在第 31-16 位(32 位数)i 中生成 0

    使用&amp; 屏蔽并仅保留最低有效 16 位。

    int32_t x = -3;
    x &= 0xFFFF;
    

    【讨论】:

    • 那么有没有办法在不使用移位的情况下只获取二进制数 0000 0000 0000 0000 1111 1111 1111 1101 中最后 16 位的值?因为我需要处理这个负数
    • 我一头雾水,你说右移是UB,这是左移x = x &lt;&lt; 16; // UB!那不应该是UB iirc
    • @KPCT 答案没有说“向右移动是 UB”。它确实具有“将负值向左移动是未定义的行为”和“将负值向右移动是实现定义的行为。”
    • 啊找到了这个newbedev.com/…我现在看到了,它取决于它是 2s 补码还是 1s。
    • @KPCT 不完全是。如上所述,即使 2s 补码或 1s 也是 UB/IDB。即使使用 2,编译器也可能以您对 UB 不期望的方式进行优化。简单地说,不要那样编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多