数据类型
整型:
char(虽然是字符类型,但是字符类型存储的时候,存储字符的ASCII码值)
unsigned char signed char
至于char有无符号,C语言中并没有明确规定
大部分编译器会认为char有符号
short
unsigned short[int] signed short[int]
short s1;//这里s1 是有符号的 等价与下面的
signed short s1;
//C语言中有规定定义短整型是默认有符号
unsigned short s1;//定义一个无符号短整型
int
unsigned int signed
浮点型:
float、double
C99中引入了long double的类型
构造类型(自定义类型):
数组类型、结构体类型、枚举类型、联合类型
指针类型:
int* pa char* pa float* pa void* pa
空类型(void)
整型在内存中的存储
原码、反码、补码
计算机中的整数有三种表达方式:原码、反码、补码
三种表达方式均有符号位和数值位两部分
符号位都是用“0”表示正数,“1”表示负数
正整数的原码、反码、补码都相同
负整数:
原码:直接翻译成二进制
反码:原码符号位不变,数值位按位取反
补码:反码 + 1
整型在内存中的存放是补码(计算机中只存在补码)
CPU的计算逻辑单元中只有加法器,减法、乘法、除法是用加法模拟的
1 -1 等价与 1 + (-1)
//原码:0000 0000 0000 0000 0000 0000 0000 0001
// +1000 0000 0000 0000 0000 0000 0000 0001
//反码:0000 0000 0000 0000 0000 0000 0000 0001
// +1111 1111 1111 1111 1111 1111 1111 1110
//补码:0000 0000 0000 0000 0000 0000 0000 0001
// +1111 1111 1111 1111 1111 1111 1111 1111
用补码进行计算:得到的结果是:
1 0000 0000 0000 0000 0000 0000 0000 0000
一个整型4个字节(即32个bit)显然 上面的计算完的补码最高位是33位,
内存中放不下就丢掉。结果自然是0.
使用补码可以将符号位和数值位统一处理
但用原码或者反码计算,结果往往不尽人意
有符号数、无符号数
有符号数的二进制值中,最高位是符号位,其他位为数据位。可以存储正数、负数
无符号数的二进制值中,全是数据位。只能存储正数
所以同类型下,无符号数可以表示的正数更大,但不能表示负数。而有符号数虽然能表示的正数较小,但在负值方向做了延伸(即能表示负数)
下面以一个字节为例:
//有符号数(首位为符号位)
//最大值:
0111 1111//转换为十进制为127
//最小值:
0000 0001(补码)//转换为十进制为-128
//无符号数(全是数值位)
//最大值:
1111 1111//转换为十进制为255
大小端(大小端字节序存储)
大端(储存)模式:
数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中
小端(储存)模式:
数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中
在计算机系统中,是以字节为单位的,每个地址单元都对应这一个字节,一个字节
为8个bit,但是在C语言中除了8bit的char之外,还有16bit的short,32bit
的long。
例如一个16bit的short类型x,在内存中的地址为0x0010,x的值为0x1122,那
么0x11为高字节,0x22为低字节,对于大端模式,就将0x11放在低地址中(即
0x0010);0x22放在高地址中(即0x0011)。小端模式恰好相反
小端模式:
整型提升
C语言中整型的运算总是以缺省整型类型的精度来进行的
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型。
发生整型提升的前提是char和short类型参与整型运算,而且运算结束后,四个字节的数据将发生截断,然后才返回值(也就是说CPU返回值的字节数仍为这个数据原本类型的字节数,而不是提升后的字节数)。
意义
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器的操作数长度
一般就是int的字节长度,同时也是CPU寄存器的长度
所以两个char类型的相加,在CPU执行时实际上要先转换为CPU内整型操作数的标
准长度
正负数的整型提升
整形提升是按照变量的数据类型的符号位来提升的(无符号整型高位补0)
char a = -1;
//a的原码:1000 0001 反码:1111 1110 补码:1111 1111
高位补充符号位(1)
1111 1111 1111 1111 1111 1111 1111 1111
char b = 1;
//a的原码、反码、补码均为:0000 0001
高位补充符号位(0)
0000 0000 0000 0000 0000 0000 0000 0001
截断
在C语言中,进行变量赋值的时候,如果将字节数多的数据类型赋给一个字节少的数据类型,会发生“截断”。
浮点型在内存中的存储
表示方法
根据国际标准IEEE,任何一个二进制浮点数可以表示成一下形式:
(-1)^ S * M * 2 ^ E
(-1)^ S:表示符号位。当S = 0,表示正数;当S = 1,表示负数。
M表示有效数字(大于等于1,小于2)
2 ^ E表示指数位
eg.
十进制的9.0,写成二进制是1001.0,相当于1.001 * 2 ^ 3
(即(-1)^ 0 * 1.001 * 2 ^ 3)
十进制的-9.0:(-1)^ 1 * 1.001 * 2 ^ 3
浮点数的精度误差:
像3.141596这种浮点数在计算器里面非常难保存(小数点后面写了很多位,但依
旧不能精确保存),这种时候会四舍五入
存储规则
浮点数对内部的划分:
float类型占4个字节(即32个bit位)
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有
效数字M。
double类型占8个字节(即64个bit位)
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有
效数字M。
IEEE对有效数字M和指数E的特殊规定:
计算机内部保存M时(1<=M<2),默认这个数的第一位是1,因此可以被舍去,只
保存小数点后面的部分。这样做是节省1位有效数字,使得浮点数精度更高。以32
位浮点数为例,将第一位的“1”舍去后,可以保存24位有效数字。
指数E是一个无符号数。如果E位8位,那么它的取值范围为0~255;如果E为11位,
那么它的取值范围为0~2047。但是,在科学计数法中,E是可以出现负数的的。所
以IEEE中规定,存入内存时E的真实值必须再加上一个中间数。对于8位的E,这个
数是127;对于11位的E,这个数是1023
E从内存中拿出来的三种情况:
1.E不全为1或不全为0:
指数E的计算值减去127(或1023),的到真实值,再将有效数字M前加上1
2.E全为0
指数E的真实值为1-127(或1-1023)。有效数字M不再加1
3.E全为1
如果有效数字全为0,表示无穷大(正负取决于符号位)