一、原码 反码 补码
1.原码
二进制表示法。最高位为符号位,表示正负;剩下位为数值位,表示数值大小。
例如(以8位举例):
- 10的原码:00001010
- -10的原码:10001010
2.反码
符号位不变,其余位取反。
例如(以8位举例):
- 10的反码:00001010
- -10的反码:11110101
正数的反码=原码
3.补码
反码+1。
例如(以8位举例):
- 10的补码:00001010
- -10的补码:11110110
正数:原码、反码、补码都相等
负数:
原码 -> 补码:符号位不变,其余位取反;+1
补码 -> 原码:
方法一:-1;符号位不变,其余位取反
方法二:符号位不变,其余位取反;+1
二、整数存储
1.计算机中的原反补规则
所有的整型数据在计算机中都已补码的形式存储和运算。
计算机在处理整型数据时,会先将其看作int类型进行处理;若超出int类型的范围,则将其看作long long型进行处理。
例如:
char a = -10;
计算机首先申请了1个字节的空间,并将这篇空间命名为a;-10的补码为11111111 11111111 11111111 11110110,将这个补码存入a这片空间,因为a只有1个字节,所以只能存入最后一个字节,即11110110。
char b = 10;
计算机首先申请了1个字节的空间,并将这篇空间命名为b;10的补码为00000000 00000000 00000000 00001010,将这个补码存入a这片空间,因为a只有1个字节,所以只能存入最后一个字节,即00001010。
2.有符号/无符号整数类型
在计算机中,char/short/int/long/long long属于有符号(signed)的整数类型,此外,计算机中还提供了一种无符号(unsigned)的整数类型。
| 类型 | 格式控制符 | 比特位使用规则 | 大小(byte) | 范围 | 特殊值 |
| 有符号(signed可写可不写)的整数家族 | |||||
| char | %hhd/%c | 1位符号位 7位数值位 | 1byte | -2^7~2^7-1 | 10000000(-2^7) |
| short | %hd | 1位符号位 15位数值位 | 2byte | -2^15~2^15-1 | 10000000 00000000(-2^15) |
| int | %d | 1位符号位 31位数值位 | 4byte | -2^31~2^31-1 | 10000000 00000000 00000000 00000000(-2^31) |
| long | %ld | 1位符号位 31位数值位 | 4byte | -2^31~2^31-1 | 10000000 00000000 00000000 00000000 (-2^31) |
| long long | %lld | 1位符号位 63位数值位 | 8byte | -2^63~2^63-1 | 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000(-2^63) |
| 无符号(unsigned)的整数家族 | |||||
| unsigned char | %hhu | 8位数值位 | 1byte | 0~2^8 | |
| unsigned short | %hu | 16位数值位 | 2byte | 0~2^16 | |
| unsigned int | %u | 32位数值位 | 4byte | 0~2^32 | |
| unsigned long | %lu | 32位数值位 | 4byte | 0~2^64 | |
| unsigned long long | %llu | 64位数值位 | 8byte | 0~2^64 | |
以char为例:
| char(1位符号位 7位数值位) | 数值 | unsigned char(8位数值位) | 数值 | |
| 0 1111111 | 127 | 01111111 | 127 | |
| 0 1111110 | 126 | 01111110 | 126 | |
| ...... | ...... | |||
| 0 0000001 | 1 | 00000001 | 1 | |
| 0 0000000 | 0 | 00000000 | 0 | |
| 1 0000000 | -128 | 10000000 | 128 | |
| 1 0000001 | -1 | 10000001 | 129 | |
| 1 0000010 | -2 | 10000010 | 130 | |
| ...... | ...... | |||
| 1 1111110 | -126 | 1 1111110 | 254 | |
| 1 1111111 | -127 | 11111111 | 255 | |
| char | 1个符号位+7个数值位 | 最大值 127(0 1111111) | 最小值 -128(1 1111111) |
| unsigned char | 8个数值位 | 最大值 255(11111111) | 最小值 0(00000000) |
- 因为char类型中10000000没有别的数可以表示,计算机强制规定它为最小值-2^7(-128)。
- 同理,short类型中,计算机强制规定10000000 00000000为最小值-2^15;
- int和long类型中,计算机强制规定10000000 00000000 00000000 00000000为最小值-2^31;
- long long类型中,计算机强制规定10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000为最小值-2^63;
3.相同字节大小转换
int main() {
//-10的原码:10000000 00000000 00000000 00001010
//-10的反码:11111111 11111111 11111111 11110101
//-10的补码:11111111 11111111 11111111 11110110
char a = -10; //只有一个字节的空间,只能存放下最后一个字节:11110110
unsigned char b = -10; //只有一个字节的空间,只能存放下最后一个字节:11110110
printf("a=%hhd,b=%hhd\n", a, b);
/*
a:11110110
1.按照%hhd(有符号char类型)的格式输出,所以要将11110110看作是1个符号位+7个数值位
2.将补码转换成原码:11110110->10001010
(符号位是1,为负数;负数的原码=补码-1,再符号位不变,其余位取反)
3.将原码转换成十进制:10001010->-10
b:11110110
1.按照%hhd(有符号char类型)的格式输出,所以要将11110110看作是1个符号位+7个数值位
2.将补码转换成原码:11110110->10001010
(符号位是1,为负数;负数的原码=补码-1,再符号位不变,其余位取反)
3.将原码转换成十进制:10001010->-10
*/
printf("a=%hhu,b=%hhu\n", a, b);
/*
a:11110110
1.按照%hhu(无符号char类型)的格式输出,所以要将11110110看作是8个数值位
2.将补码转换成原码:11110110->10001010(正数的原码、反码、补码相同)
3.将原码转换成十进制:10001010->138
b:11110110
1.按照%hhu(无符号char类型)的格式输出,所以要将11110110看作是8个数值位
2.将补码转换成原码:11110110->10001010(正数的原码、反码、补码相同)
3.将原码转换成十进制:10001010->138
*/
return 0;
}4.不同字节大小转换
(1)小字节转大字节
符号位不变,数值位不变,其余位补符号位的数字。
int main() {
//-10的原码:10000000 00000000 00000000 00001010
//-10的反码:11111111 11111111 11111111 11110101
//-10的补码:11111111 11111111 11111111 11110110
char a = -10; //只有一个字节的空间,只能存放下最后一个字节:11110110
unsigned char b = -10; //只有一个字节的空间,只能存放下最后一个字节:11110110
printf("a=%hd,b=%hd\n", a, b);
/*
a:11110110 -> a的类型是有符号char类型,符号位:1
1.按照%hd(有符号short类型)的格式输出,所以要先将11110110扩充为2个字节:
11110110->11111111 11110110
(符号位不变,数值位不变,其余位补符号位的数字,即补1)
2.将11111111 11110110看作是1个符号位+15个数值位
3.将补码转换成原码:11111111 11110110->10000000 00001010
(符号位是1,为负数;负数的原码=补码-1,再符号位不变,其余位取反)
4.将原码转换成十进制:10000000 00001010->-10
b:11110110 -> b的类型是无符号char类型,符号位:0
1.按照%hd(有符号short类型)的格式输出,所以要先将11110110扩充为2个字节:
11110110->00000000 11110110
(符号位不变,数值位不变,其余位补符号位的数字,即补1)
2.将00000000 11110110看作是1个符号位+15个数值位
3.将补码转换成原码:00000000 11110110->00000000 11110110
(符号位是0,为正数;正数的原码、反码、补码相同)
4.将原码转换成十进制:00000000 11110110->246
*/
printf("a=%hu,b=%hu\n", a, b);
/*
a:11110110 -> a的类型是有符号char类型,符号位:1
1.按照%hu(无符号short类型)的格式输出,所以要先将11110110扩充为2个字节:
11110110->11111111 11110110
(符号位不变,数值位不变,其余位补符号位的数字,即补0)
2.将11111111 11110110看作是16个数值位
3.将补码转换成原码:11111111 11110110->11111111 11110110
(正数的原码、反码、补码相同)
4.将原码转换成十进制:11111111 11110110->65526
b:11110110 -> b的类型是无符号char类型,符号位:0
1.按照%hd(有符号short类型)的格式输出,所以要先将11110110扩充为2个字节:
11110110->00000000 11110110
(符号位不变,数值位不变,其余位补符号位的数字,即补0)
2.将00000000 11110110看作是16个数值位
3.将补码转换成原码:00000000 11110110->00000000 11110110
(正数的原码、反码、补码相同)
4.将原码转换成十进制:00000000 11110110->246
*/
return 0;
}(2)大字节转小字节
直接强行截取。
int main() {
//-10的原码:10000000 00000000 00000000 00001010
//-10的反码:11111111 11111111 11111111 11110101
//-10的补码:11111111 11111111 11111111 11110110
short a = -10;
//只有两个字节的空间,只能存放下最后两个字节:11111111 11110110
unsigned short b = -10;
//只有两个字节的空间,只能存放下最后两个字节:11111111 11110110
printf("a=%hhd,b=%hhd\n", a, b);
/*
a:11111111 11110110
1.按照%hhd(有符号char类型)的格式输出,所以要先将11111111 11110110截取为1个字节:
11111111 11110110->11110110
2.将11110110看作是1个符号位+7个数值位
3.将补码转换成原码:11110110->10001010
(符号位是1,为负数;负数的原码=补码-1,再符号位不变,其余位取反)
4.将原码转换成十进制:10001010->-10
b:11111111 11110110
1.按照%hhd(有符号char类型)的格式输出,所以要先将11111111 11110110截取为1个字节:
11111111 11110110->11110110
2.将11110110看作是1个符号位+7个数值位
3.将补码转换成原码:11110110->10001010
(符号位是1,为负数;负数的原码=补码-1,再符号位不变,其余位取反)
4.将原码转换成十进制:10001010->-10
*/
printf("a=%hhu,b=%hhu\n", a, b);
/*
a:11110110
1.按照%hhu(无符号char类型)的格式输出,所以要先将11111111 11110110截取为1个字节:
11111111 11110110->11110110
2.将11110110看作是8个数值位
3.将补码转换成原码:11110110->11110110
(正数的原码、反码、补码相同)
4.将原码转换成十进制:11110110->246
b:11110110
1.按照%hhu(无符号char类型)的格式输出,所以要先将11111111 11110110截取为1个字节:
11111111 11110110->11110110
2.将11110110看作是8个数值位
3.将补码转换成原码:11110110->11110110
(正数的原码、反码、补码相同)
4.将原码转换成十进制:11110110->246
*/
return 0;
}总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论