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

let*_*ism 6 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;
}
Run Code Online (Sandbox Code Playgroud)

我期望第一个位移(x << 4)评估为0xbcd0,然后右位移以领先0- 0x0bcd。但是,实际输出为0xabcd

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

uint16_t a = (x >> 4) << 4;
Run Code Online (Sandbox Code Playgroud)

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

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

ens*_*nsc 9

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

uint16_t a = (int)((int)x << 4) >> 4;
Run Code Online (Sandbox Code Playgroud)

因此高位不会被剥离。