为什么复合位移位未将前半字节设置为0?

时间:2019-05-02 22:59:38

标签: c bit-shift

我试图清除16位无符号整数(将其设置为0)中的第一个半字节。

我尝试的方法之一是先左移然后右移以清除前四位。

这是我的程序。

#include <stdio.h>
#include <stdint.h>

int main() {
    uint16_t x = 0xabcd; // I want to print out "bcd"
    uint16_t a = (x << 4) >> 4;

    printf("After clearing first four bits: %x\n", a);

    return 0;
}

我期望第一个移位(x << 4)的值为0xbcd0,然后向右移位以将前导0推到前面-0x0bcd。但是,实际输出为0xabcd

更让我困惑的是,如果我尝试使用相同的方法来清除最后四位,

uint16_t a = (x >> 4) << 4;

它工作正常,我得到预期的输出:abc0

为什么在上面的程序中,右移没有将前导0压入?

2 个答案:

答案 0 :(得分:9)

由于整数提升而发生。在int大于16位的系统上,您的表达式将转换为

uint16_t a = (int)((int)x << 4) >> 4;

因此不清除高位。

答案 1 :(得分:0)

如果要打印“ bcd”,也许可以这样:

#include <stdio.h>
#include <stdint.h>

int main() {
    uint16_t x = 0xabcd; // I want to print out "bcd"        // step 1
    uint16_t c = x << 4 ;                                    // step 2
    uint16_t a = c >> 4;                                     // step 3

    printf("After clearing first four bits: %x\n", a);

    return 0;
}

上面的输出是:

After clearing first four bits: bcd

解释:

运行步骤1时:

x is 1010101111001101 (binary)          // 1010(a) 1011(b) 1100(c) 1101(d)

转到步骤2:

c is 1011110011010000 (binary)          // 1011(b) 1100(c) 1101(d) 0000(0)

最后转到步骤3:

a is 101111001101 (binary)              // 1011(b) 1100(c) 1101(d)