整型家族(内置):char (字符存储的是ASC II码,是整型)、short、int、long、long long;
浮点数家族(内置):float、double;
构造类型(自定义):数组类型、结构体类型(struct)、枚举类型(enum)、联合类型(union);
指针类型:int*、float*...;
空类型:void;
一、整型在内存中的存储
1.1 原码、反码、补码
整型数据的二进制表示形式有三种:原码、反码、补码;三种表示形式,均有符号位、数值位两部分;符号位都是用“0”表示正数、“1”表示负数;
- 正数的原反补相同;
- 负数的原反补各不相同:1)原码:将数值翻译成二进制;2)反码:除符号位不变,其它位原码按位取反;3)补码:反码+1;
对于整型,内存中存储的是补码;原因在于,存储补码可以将数值位和符号位统一处理;
//对于数值位和符号位统一处理的小理解,CPU只有加法,没有减法
1 + 1 ——> 1 + (-1)
原码:
0000 0000 0000 0000 0000 0000 0000 0001 —— 1
1000 0000 0000 0000 0000 0000 0000 0001 —— -1
1000 0000 0000 0000 0000 0000 0000 0010 —— -2
补码:
0000 0000 0000 0000 0000 0000 0000 0001 —— 1
1111 1111 1111 1111 1111 1111 1111 1111 —— -1
0000 0000 0000 0000 0000 0000 0000 0000 —— 0
扩展:
- 整型家族的类型,都有有符号和无符号的分别;
- signed int == int,平时写int都是省略了;
- char是个例外,char不知道是signed char还是unsigned char,C语言标准里没有规定;
- signed char的范围是(-128,127)【0-127-(-128)-(-1)- 0轮回】这里的-128是根据定义来的,原反补求解法算不出;unsigned char的范围是(0,255);
- 整型的表示范围在“limits.h”中定义;
signed char a = -1;
//1111 1111 1111 1111 1111 1111 1111 1111 —— (-1)
//1111 1111 —— (a)
//%d整型提升,有符号数按符号位补全
//1111 1111 1111 1111 1111 1111 1111 1111 —— (-1)
unsigend char b = -1;
//1111 1111 1111 1111 1111 1111 1111 1111 —— (-1)
//1111 1111 —— (a)
//%d整型提升,无符号数全补0
//0000 0000 0000 0000 0000 0000 1111 1111 —— (255)
printf("a=%d,b=%d", a, b); // -1 255
1.2 大小端
字节序 —— 是以字节为单位讨论存储顺序;
小端字节序 —— 低位字节的内容存放在低地址处,高位字节的内容存放在高地址处;
大端字节序 —— 低位字节的内容存放在高地址处,高位字节的内容存放在低地址处;
大小端是硬件决定的!!!
// 写个程序来判断所在机器是大端存储还是小端存储
int a = 1; // ox 00 00 00 01
if((* ((char*)&a) ) == 1)
printf("小端");
else
printf("大端");
二、浮点数在内存中的存储
tips:浮点数的表示范围在“float.h”中定义;
根据国际标准IEEE754,任意一个二进制浮点数可以表示成如下形式:
- (-1)^S * M * 2^E
- (-1)^S表示符号位,S=0表示正数,S=1表示负数;
- M表示有效数字,大于等于1,小于2;
二进制的权重:... 2^3 2^2 2^1 2^0 小数点 2^(-1) 2^(-2) 2^(-3) ...
例子:5.5(十进制)写成二进制为 101.1 写成科学计数法为 1.011 * 2^2 (二进制) 写成国际标准形式为 (-1)^0 * 1.011 * 2^2 —— S=0、M=1.011、E=2
IEEE754规定,对于32位的浮点数(float),第1位是符号位S,接下来8位是指数位E,剩下23位为有效数字M;
IEEE754规定,对于64位的浮点数(double),第1位是符号位S,接下来11位是指数位E,剩下52位为有效数字M;
关于M的特殊规定:因为M的第一位总是1,因此可以不保存;【那0.000怎么办?】
关于E的特殊规定:1)存入:首先E是一个无符号整数,那如果它是8位,它的范围是[0,255],如果它是11位,它的范围是[0,2047]。但科学计数法中E可能为负数,因此IEEE754规定,存入内存时必须加上一个中间值,对于8位E中间值是127,对于11位中间值是1023;2)取出:不为全零全一,那么减去127(1023)得到真实值;E为全零,这时E = -127(-1023)+1,且M不补1,而取0;E为全1,有效数字M=0表示正负无穷大;