3 原码、反码、补码
3.1 知识点补充
在计算机内部,所有信息都是用二进制数串的形式表示的。整数通常都有正负之分,计算机中的整数分为无符号的和带符号的。无符号的整数用来表示0和正整数,即自然数;带符号的正数可以表示所有的整数。
由于计算机中符号和数字一样,都必须用二进制数串来表示,因此,正负号也必须用0、1来表示。通常我们用最高的有效位来 表示数的符号(当用8位来表示一个整数时,第8位即为最高有效位,当用16位来表示一个整数时,第16位即为最高有效位。)0表示正号、1表示负号。
这种正负号数字化(0表示正号、1表示负号)的机内表示形式就称为机器码或者机器数,而相应的机器外部用正负号表示的数称为真值。将一个真值表示成二进制字串的机器数的过程就称为编码。
无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。带符号整数有原码、反码、补码等几种编码方式。
**原码即直接将真值转换为其相应的二进制形式,而反码和补码是对原码进行某种转换编码方式。**正整数的原 码、反码和补码都一样,负数的反码是对原码的除符号位外的其他位进行取反后的结果(取反即如果该位为0则变为1,而该位为1则变为0的操作)。而补码是先求原码的反码,然后在反码的末尾位加1 后得到的结果,即补码是反码+1。IBM-PC中带符号整数都采用补码形式表示。
注意,只是带符号的整数采用补码存储表示的,浮点数另有其存储方式。
- 正数的补码是其本身
- 负数的反码,符号位不变,其余的按位取反
- 负数的补码,反码加1
对于字长为8位有符号的int,因为最高为符号位,占1位,所以最小为(1111111)2 = (-127)10,最大为(0111111)2 = (127)10;即其原码范围为:-127~127
有符号的8位二进制的原值表达范围为:-127至127,此时共255个数字;然而,8位二进制 的补码排列共有 = 256个,0000 0000 至1111 1111 。
| 补码组合 | 范围 | 个数 |
|---|---|---|
| 0000 0000 - 0111 1111 | 0 ~+127 | 128 |
| 10000000 | 多余的一种组合待定 | 1 |
| 1000 0001 - 1111 1111 | -1~-127 | 127 |
**10000000 **看似要被浪费掉了啊!其实不然,( 100000000 ) 2 = ( 2^7 ) 10 = ( 128 ) 10,这个组合要利用起来,不能太偏离数值意义,表示128,显得更直观。
**从大到小,依次减1看一下规律:**| 十进制 (字长8bit) | 原码 | 反码 | 补码 |
|---|---|---|---|
| 127 | 0111 1111 | 0111 1111 | 0111 1111 |
| 126 | 0111 1110 | 0111 1110 | 0111 1110 |
| …… | …… | …… | …… |
| 10 | 0000 1010 | 0000 1010 | 0000 1010 |
| …… | …… | …… | …… |
| 2 | 0000 0010 | 0000 0010 | 0000 0010 |
| 1 | 0000 0001 | 0000 0001 | 0000 0001 |
| +0 | 0000 0000 | 0000 0000 | 0000 0000 |
| -1 | 1000 0001 | 1111 1110 | 1111 1111 |
| -2 | 1000 0010 | 1111 1101 | 1111 1110 |
| …… | …… | …… | …… |
| -10 | 10001010 | 11110101 | 11110110 |
| …… | …… | …… | …… |
| -127 | 11111111 | 10000000 | 10000001 |
| 待定 | 10000000 |
从递减规律中,发现,**10000000 **表示-128更合适。
即规定:-128的补码为 10000000
求10 -10 0 -128 127 的原码、反码、补码
| 十进制 (字长8bit) | 原码 | 反码 | 补码 |
|---|---|---|---|
| 10 | 00001010 | 00001010 | 00001010 |
| -10 | 10001010 | 11110101 | 11110110 |
| -1 | 1000 0001 | 1111 1110 | 1111 1111 |
| +0 | 00000000 | 00000000 | 00000000 |
| -0 | |||
| -128 | 无 | 无 | 10000000 |
| 127 | 01111111 | 01111111 | 01111111 |
| -127 | 11111111 | 10000000 | 10000001 |
+0和-0的补码是一样的。即 0的补码只有一种表示,0的补码是0000 0000,
# 四 输出结果,解释为什么是这样的char c = 128;
printf("%d\n",c);
printf("%hhd\n",c);
printf("%hd\n",c);
printf("%hu\n",c);
4.1 格式输出符
| 格式符号 | 意义 |
|---|---|
| %a | 浮点数、十六进制数字和p-记数法 (C99) |
| %A | 浮点数、十六进制数字和P-记数法 (C99) |
| %c | 一个字符 |
| %d | 有符号十进制整数 |
| %e | 浮点数、e-记数法 |
| %E | 浮点数、E-记数法 |
| %f | 浮点数,十进制记数法 |
| %g | 根据数值不同自动选择%f或者%e。%e格式在指数小于-4或者大于等于精度时使用 |
| %G | 根据数值不同自动选择%f或者%E。%E格式在指数小于-4或者大于等于精度时使用 |
| %i | 有符号十进制整数 (与%d相同) |
| %o | 无符号八进制整数 |
| %p | 指针(就是指地址) |
| %s | 字符串 |
| %u | 无符号十进制整数 |
| %x | 使用十六进制数字0f 的无符号十六进制整数 |
| %X | 使用十六进制数字0F的无符号十六进制整数 |
| %% | 打印一个百分号 |
| 修饰符 | 意义 | 示例 |
|---|---|---|
| h | 和整数转换说明符一起使用,表示一个short int 或者 unsigned short int 类型数值。 | "%hd |
| hh | 和整数转换说明符一起使用,表示一个signed char 或者unsigned char类型数值。 | "%hhd" |
| j | 和整数转换说明符一起使用,表示一个intmax_t或uintmax_t值。 | "%jd" |
| l | 和整数说明符一起使用,表示一个long int 或者unsigned long int 类型值。 | "%8lu" |
| ll | 和整数说明符一起使用,表示一个long long int或 unsigned long long int 类型值 (C99)。 | "%lld" |
| L | 和浮点转换说明符一起使用,表示一个long double值。 | "%8.4Le" |
| t | 和整数转换说明符一起使用,表示一个ptrdiff_t值(与两个指针之间的差相对应的类型) (C99) | "%td" |
| - | 项目是左对齐的,也就是说,会把项目打印在字段的左侧开始处 | "%-20s" |
| + | 有符号的值若为正,则显示带加号的符号;若为负,则带减号的符号。 | "%+3.2" |
| (空格) | 有符号的值若为正,则显示时带前导空格(但是不显示符号);若为负,则带减号符号。+标志会覆盖空格标志。 | "% 3.2" |
| # | 使用转换说明的可选形式。若为%o格式,则以0开始;若为%x和%X格式,则以0x或0X开始,对于所有的浮点形式,#保证了即使不限任何数字,也打印一个小数点字符。对于%g和%G格式,它防止尾随零被删除。 | "%#o" |
| 0 | 对于所有的数字格式,用前导零而不是用空格填充字段宽度。如果出现-标志或者指定了精度(对于整数)则忽略该标志。 | "%010d" |
char c = 128;
此处是将一个int赋值给一个char类型变量,进行隐式类型转换.int型数值赋给char型变量时,只保留其最低8位,高位部分舍弃。
首先,整型128在一个字长为4个字节的的原码为00000000 00000000 00000000 10000000,当把一个int类型赋值给一个有符号的char类型时,高位被舍弃。实际给c的是


/1 
