You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中按位取反对数值与变量的行为差异技术咨询

无符号字符取反结果差异的问题解析

遇到的现象

运行代码后得到如下输出:

test1: 0x00000002 0b00000010 (1 bytes)
test2: 0x000000fd 0b11111101 (1 bytes)
~test1: 0xfffffffd 0b4294967285 (4 bytes)

我无法理解为何在所有类型均为无符号的情况下,~test1与~(0x02)的结果不同——test1的值就是0x02,但~test1在正确取反后左侧多了3字节的1。

问题代码

#include <stdio.h>
int binConv(int num) {
    if (num == 0) {
        return 0;
    } else {
        return (num % 2) + 10 * binConv(num / 2);
    }
}
int main() {
    unsigned char test1;
    unsigned char test2;
    test1=0x02;
    test2=~(0x02);
    printf(" test1: 0x%08x 0b%08u (%d bytes)\n",test1,binConv(test1),sizeof(test1));
    printf(" test2: 0x%08x 0b%08u (%d bytes)\n",test2,binConv(test2),sizeof(test2));
    printf("~test1: 0x%08x 0b%08u (%d bytes)",~test1,binConv(~test1),sizeof(~test1));
    return 0;
}

问题拆解与解答

这事儿其实是C语言里的**整数提升(Integer Promotion)**在搞鬼,我给你一步步说清楚:

  • 先看~(0x02)的逻辑
    0x02是整数字面量,C语言默认把它当成int类型(通常是4字节)。对它取反后得到0xfffffffd,但当把这个值赋值给unsigned char类型的test2时,会自动截断——只保留低8位的0xfd(二进制11111101),所以最终test2的输出是符合预期的1字节结果。

  • 再看~test1的逻辑
    test1是unsigned char(1字节),当你对它使用~运算符时,C语言会触发整数提升规则:把小于int的整数类型自动转换成int类型。所以test1的0x02会先被转成int类型的0x00000002,再取反得到0xfffffffd——这个结果直接传给了printf,没有经过截断,所以你看到的是4字节的数值,也就是左侧多了3字节的1。而且sizeof(~test1)输出4也能证明:取反后的结果已经是int类型,不再是原来的unsigned char了。

  • 怎么让~test1和~(0x02)输出一致?
    只要把~test1强制转回unsigned char类型就行,比如修改最后一行printf:

    printf("~test1: 0x%08x 0b%08u (%d bytes)",(unsigned char)~test1,binConv((unsigned char)~test1),sizeof((unsigned char)~test1));
    

    这时候输出就会和test2完全一样啦。

内容的提问来源于stack exchange,提问作者Yelneerg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:28:50