char类型的位运算在转换为int类型时失败了。

4

我正在尝试在C中进行位运算。这是我的代码:

int main() {
    char c = 127;
    c <<= 1;
    if (c == 0xfe) {
        printf("yes");
    }
    else {
        printf("No");
    }
    return 0;
}

系统控制台输出编号。 我期望收到的是肯定的回答。 位移后c中的值为ffffffffe。 看起来系统已经将8位转换为32位。有人能帮忙吗。


1
在进行位运算时,几乎总是应该使用无符号类型。 - Barmar
位运算背后的机制是什么?有何不同之处?您能否向我推荐一些相关的论文? - Akrios
https://dev59.com/a2865IYBdhLWcg3wEKOZ - Barmar
1个回答

7
你已经正确地确定了低位字节的内容,即0xfe。但实际上这里发生了更多的事情:当你写入数据时,数据被视为无符号整数,因此十六进制值0xfe实际上被解释为 254 而不是 -2。这意味着如果你从内存中读取这个字节并将其转换为有符号整数,你将得到一个错误的结果。
if (c == 0xfe) {
    ...
}

你正在比较一个字符型变量char c和一个整型常量int 0xfe。在这种情况下,C语言规则要求将char c提升为int类型进行比较。由于你的平台上char是有符号的,所以0xfe会被提升为0xfffffffe,这就是后续比较失败的原因。
如果你想用char类型进行比较,请将0xfe强制转换为char类型,像这样:
if (c == (char)0xfe) {
    ...
}

演示1

相比之下,无符号字符在使用int提升时不会给你带来麻烦,因为它们可以很好地适应int的范围:

unsigned char c = 127;
c<<=1;
if (c == 0xfe) { // No casting is necessary
    ...
}

演示 2。

注意:由于 char 溢出,c <<= 1 的行为是实现定义的。


2
请注意,c <<= 1; 中的行为是由于溢出而实现定义的。 - Eric Postpischil
@EricPostpischil 这是真的,符号扩展值的行为也是如此。感谢您的评论! - Sergey Kalinichenko
如果我错了,请纠正我。本质上,c 中的值仍然是 0xfe,但通过调用 printf() 函数进行了提升。· - Akrios
@Akrios 0xfffffffe 只有 32 位(每个 4 位组成的 8 个半字节)。它不是升级到 int 的操作,而是其他操作:打印、比较等。C 这样做很多,所以在使用带符号字符时需要小心。另一方面,无符号字符则不会给您带来任何麻烦。请参见编辑。 - Sergey Kalinichenko
@dasblinkenlight,太棒了。unsigned解决了问题。 - Akrios
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接