整数在计算机里:为什么存的是补码,输出的却是原码?

整数在计算机里:为什么存的是补码,输出的却是原码? 我们都知道计算机用补码存整数但printf出来的却是原码。这中间发生了什么本文带你走一遍从代码到内存再到输出的完整流程。一、先记住这一句整数在内存中永远存补码但输出时会根据格式控制符转成原码显示。为什么存补码计算机只用加法器就能处理减法输出原码人类只看懂带符号位的原始形式二、完整流程阶段步骤存入内存原始数值 → 写出原码 → 按变量类型调整位数 → 转补码 → 存入内存输出屏幕读取补码 → 按格式符调整位数 → 转原码 → 转十进制 → 显示看不懂没关系后面每步都会拆开细讲看完再回来看这张表就懂了。三、整数存入计算机原码 → 补码当你定义一个变量并赋值时如char a -5或long long b 100计算机按以下两步处理① 写出原码直接按定义的类型写出原码。定义原码char a -5100001018位short b -510000000 0000010116位int c -510000000 00000000 00000000 0000010132位long long d -510000000 00000000 00000000 00000000 00000000 00000000 00000000 0000010164位规则最高位是符号位0正1负后面跟数值绝对值的二进制。② 转成补码最终存储规则正数/无符号数补码 原码不变有符号负数补码 原码的符号位不变数值位取反再加1示例步骤char a -58位int b -532位①原码1000010110000000 00000000 00000000 00000101②取反1111101011111111 11111111 11111111 11111010③加11111101111111111 11111111 11111111 11111011内存1111101111111111 11111111 11111111 11111011四、计算机输出整数补码 → 原码当你用printf输出时如printf(%d, a)计算机反向操作① 读取补码从内存中取出之前存的补码11111011以char a -5为例② 按格式控制符调整位数看你是用%d、%u、%hd还是%hhd按目标类型调整位数情况A格式符位数 变量位数 → 符号扩展有符号数高位补符号位正数补0负数补1无符号数高位补0情况B格式符位数 变量位数 → 截取低位情况C格式符位数 变量位数 → 不变示例char a -5用%d输出阶段位数二进制char补码8位11111011符号扩展负数补132位11111111 11111111 11111111 11111011③ 还原成原码类型还原规则正数/无符号数补码直接就是原码无需转换有符号负数补码 → 减1 → 数值位取反符号位不变示例%d输出-5步骤二进制补码规整后11111111 11111111 11111111 11111011减111111111 11111111 11111111 11111010取反符号位不变10000000 00000000 00000000 00000101原码结果 -5④ 转十进制输出原码10000000 00000000 00000000 00000101 -5屏幕上显示-5五、示例同一份内存不同的输出结果示例1%d vs %uchar a -5; // 内存中存的是补码11111011 printf(%d\n, a); // 输出-5 printf(%u\n, a); // 输出4294967291用%d输出11111011→ 符号扩展成32位11111111 11111111 11111111 11111011→ 减1取反得原码10000000 00000000 00000000 00000101-5用%u输出11111011→ 符号扩展成32位11111111 11111111 11111111 11111011→ 直接当无符号数解读 4294967291核心同一内存不同格式符输出不同。示例2%hu 输出char a -5; printf(%hu\n, a); // 65531处理流程整型提升11111011→ 符号扩展成32位11111111 11111111 11111111 11111011截取低16位11111111 11111011当无符号数解读65531示例3-128的特殊情况char a -128; printf(%hu\n, a); // 65408-128的补码是10000000处理流程整型提升10000000→ 符号扩展成32位11111111 11111111 11111111 10000000截取低16位11111111 10000000当无符号数解读65408六、核心总结6.1.存储与输出的完整流程存储时按定义类型写原码 → 负数取反加一转补码 → 存内存输出时取补码 → 按格式符做整数提升/截断 → 负数减一取反转原码 → 显示6.2.三个核心概念计算机只认补码内存里永远存的是补码人类只看原码输出时一定要还原成原码格式控制符决定最终看到什么同一块内存用%d和%u看完全不同6.3.整数提升规则小类型char、short做运算或传参时先转成int有符号按符号位扩展无符号补0七、练习题分析下面代码的输出char a -1; printf(%d %u %hu %hhu\n, a, a, a, a);答案%d-1%u4294967295%hu65535%hhu255你能按流程推出来吗结语现在你明白了吗存补码是为了让计算机好计算输出原码是为了让人类能看懂中间经历了整数提升 符号扩展/截断 原反补转换下次再看到奇怪的输出结果不妨按这个流程走一遍保证能看懂