文章目录
类型 | 描述 |
---|---|
char | 通常是一个字节(八位), 这是一个整数类型。 |
int | 整型,4 个字节,取值范围 -2147483648 到 2147483647,最高位表示符号 |
float | 单精度浮点值。单精度是这样的格式,1位符号,8位指数,23位小数。 |
double | 双精度浮点值。双精度是1位符号,11位指数,52位小数。 |
void | 表示类型的缺失。 |
注意:变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。
1、signed char类型的存储
有符号类型变量在存储时,是存储变量的补码。无符号变量存储时,储存原码
1.1 原码
最高位为符号位,0表示正数,1表示负数。
例如:
X = 0b11 (3),四比特表示原码 = 0011(3) ;
X = - 0b11(-3) ,四比特表示原码 = 1011(11) ;
1.2 反码
最高位为符号位,0表示正数,1表示负数。
正数的反码等于本身,负数的反码除符号位外,各位取反:
例如:
X = 0b11 (3),四比特表示原码 = 0011(3),对应反码为 = 0011(3) ;
X = - 0b11(-3) ,四比特表示原码 = 1011(11),对应反码为 = 1100(12) ;
1.3 补码
最高位为符号位,0表示正数,1表示负数。
正数的补码等于本身,负数的补码等于反码+1:
例如:
X = 0b11 (3),四比特表示原码 = 0011(3),对应反码为 = 0011(3) ,补码为 = 0011(3);
X = - 0b11(-3) ,四比特表示原码 = 1011(11),对应反码为 = 1100(12),补码为1101(13) ;
1.4存储补码的作用
为了方便展示,把变量简化成为4bit 。
二进制 | 原码存储表示值 | 反码存储表示值 | 补码存储表示值 |
---|---|---|---|
0000 | 0 | 0 | 0 |
0001 | 1 | 1 | 1 |
0010 | 2 | 2 | 2 |
0011 | 3 | 3 | 3 |
0100 | 4 | 4 | 4 |
0101 | 5 | 5 | 5 |
0110 | 6 | 6 | 6 |
0111 | 7 | 7 | 7 |
1000 | -8 | -7 | -8 |
1001 | -1 | -6 | -7 |
1010 | -2 | -5 | -6 |
1011 | -3 | -4 | -5 |
1100 | -4 | -3 | -4 |
1101 | -5 | -2 | -3 |
1110 | -6 | -1 | -2 |
1111 | -7 | -8 | -1 |
注意:把首尾连接,形成一个圆看,更加容易理解。
2、float的存储
1.1储存格式
C语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit, double数据占用64bit
无论是单精度还是双精度在存储中都分为三个部分:
- 符号位(Sign) :0代表正,1代表为负
- 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储
- 尾数部分(Mantissa):尾数部分
其中float的存储方式如下图所示:
而双精度的存储方式为:
2.2转换流程
- 把小数转换成二进制数
- 用科学计数法表示
- 指数部分+127存放在指数位,小数部分存放在尾数部分
解析:
- +127原因:指数范围是-127~+128,为了表示负数,+127做偏移
- 为什么只存储小数部分:二进制除0外,无论什么数,用科学计数法都是整数1开头,因此没必要存储整数1,eg:1.0001010111*e^1010
2.3 float存储示例
以数字6.5为例,看一下这个数字是怎么存储在float变量中的:
- 先来看整数部分,模2求余可以得到二进制表示为110。
- 再来看小数部分,乘2取整可以得到二进制表示为.1
- 拼接在一起得到110.1然后写成类似于科学计数法的样子,得到1.101*2^2 。
- 从上面的公式中可以知道符号为正,尾数是101,指数是2。
- 符号为正,那么第一位填0,指数是2,加上偏移量127等于129,二进制表示为10000001,填到2-9位,剩下的尾数101填到尾数位上即可
S | E | E | E | E | E | E | E | E | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M | M |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- 内存中二进制数01000000 11010000 00000000 00000000表示的就是浮点数6.5
2.4 范围
最大值表示范围:[-3.4028235E38, 3.4028235E38]
-1.1111111 1111111 11111111*2^127=-3.4028235E38
符号 | 指数 | 尾数 |
---|---|---|
1 | 1111 1110 | 111 1111 1111 1111 1111 1111 |
-1.1111111 1111111 11111111*2^127=3.4028235E38
符号 | 指数 | 尾数 |
---|---|---|
0 | 1111 1110 | 111 1111 1111 1111 1111 1111 |
最小正值为:1.1754943508222875079687365372222e-38
1.000*2^-126
符号 | 指数 | 尾数 |
---|---|---|
0 | 0000 0001 | 000 0000 0000 0000 0000 |
2.5 精度
float最少能保证7~8位的有效数值,因为23位的位数,实则是24位位数能表示的范围是0-16777216,7位能全部表示,8位部分能表示,因此超过16777216的整数部分就不能准确的表示了,同样的小数部分也不是都能准确表示的,小数分辨率可以很高也可以很低,具体看小数占多少位,最多可以占-126位。当整数比较大,接近20位二进制才能表示时,小数位就只有4位了,这时精度就只有2^-4=0.0625。
2.6 float 特殊值
我们知道float存储浮点数的形式是(±)1.b *2^c,因为尾数位前面一直是个1,所以无论b和c取什么样的值,都无法得到0,所以在float的表示方法中有一些特殊的约定,用来表示0已经其他的情况。
float的内存表示指数位数有8位,范围是[0, 255],考虑偏移量实际的指数范围是[-127,128],但实际情况下指数位表示一般数字时不允许同时取0或者同时取1,也就是指数位的实际范围是[-126,127],而指数取-127和128时有其特殊含义,具体看下面表格:
参考地址
https://www.lidihuo.com/c/c-tokens.html
https://blog.csdn.net/slience_J/article/details/51965009
https://blog.csdn.net/ly_w1989/article/details/50213011
https://blog.csdn.net/albertsh/article/details/92385277