C 和位移位

C and bitwise shifts

我可能有一个关于 C 中的位移位的新问题。我想编写一个宏,它将 return unsigned char 的第 n 位。我最初的想法是左移 (7-n),将位移至 MSB 位置,然后右移 7,将位移至 LSB。这没有用,所以我开始在非宏观环境中进行测试。

所以这不起作用:

int main() {
    unsigned char c=126,d,i;
        
    for(i=0;i<8;++i){
        d = (c<<(7-i)) >> 7;
        printf("%d bit: %d\n",i,d);
    }
    return 0;
}

但这行得通:

int main() {
    unsigned char c=126,d,i;
        
    for(i=0;i<8;++i){
        d = (c<<(7-i));
        d >>= 7;
        printf("%d bit: %d\n",i,d);
    }
    return 0;
}

我用 &mask 解决了原来的问题.. d=(c>>i)&1;。但是,我仍然不明白为什么这两个不同...有什么想法吗?

unsigned char c=126i==0:

(c<<(7-i)) 是一个 14 位值。

d = (c<<(7-i)) >> 7; 保留该 14 位值然后右移 7:保留信息。

d = (c<<(7-i)); d >>= 7; 在保存到 d 时将 14 位值截断为 8 位,然后右移:信息丢失。

获取位数 n 的正确方法是 val & (1u << n)。对于宏,这将是:

#define BIT(val, n) ( (val) & (1u << (n)) )

如果您想要 1 或 0,则只需 (bool)BIT(0x80, 7);


虽然一般来说,请不要发明这样的宏,因为 val & (1u << n) 已经是最可读的规范形式。

这个u8 = val & (1u << 7);远远优于u8 = BIT(val,7);