C语言——数据的类型和存储

1.类型的基本归类

类型主要分为四大类,内置类型,自定义类型(构造类型),指针类型和空类型(void)

1.内置类型

内置类型又分为整形和浮点型

整形分为有符号和无符号

char
unsigned char     [signed] char

short
unsigned short [int]        [signed] short [int]

int
unsigned int      [signed] int

long
unsigned-long [int]         [signed] long [int]

[ ]框起来的表示在实际操作中常常被省略的部分
 

浮点型

单精度浮点型——float

双精度浮点型——double

2.自定义类型(构造类型)

自定义类型(构造类型)有很多类型,如下

a. 数组类型

b. 结构体类型struct

c. 枚举类型enum

d. i联合类型union

3.指针类型

int*

float*

double*

void*

char*

4.空类型

空类型是一种特殊的类型

void表示空类型(无类型)
通常应用于函数的返回类型、函数的参数。指针类型。

 

void的使用方法,如下图

 

当test()括号中有一个void时,表示test函数不需要传递参数,若传递参数,如下面的test(100),系统就会报错。相应的,如果test()括号里没有void,main中的test(100),也会使test正常工作,不会报错,这是C语言一直存在的一个模糊问题。

2.数据的存储

1.整形的存储

正数,负数都是按补码形式存放,原因如下

正数的原反补码相同 。

那么负数的补码如何转换呢,首先要把它转换成反码,方法是除了符号位外其他为取反,也就是0变1,1变0,如何在给反码加1就转换成了补码,下面举个例子:

有一个int型十进制数-5,原码就是把它转换成二进制,也就是

                  10000000 00000000 00000000 00000101

最高位为符号位,为负数时为1,为正数时为0。除符号位取反得到反码为

                   11111111 11111111 11111111 11111010

再给反码加1得到补码

                    11111111 11111111 11111111 11111011

这就是负数补码的转化过程

为什么说补码可以让加法和减法统一处理呢

看例子:如int a=1;int b=1;如何实现a-b呢

由于CPU只有加法器,a-b转化为a+(-b)

若按原码,则是00000000000000000000000000000001      与

                         10000000000000000000000000000001       相加

答案为              10000000000000000000000000000010   这不是正确答案

但是按照补码则是     00000000 000000000000000000000001   与

                 1111 1111 1111 1111 1111 1111 1111 1111相加

答案为               1 0000 0000 0000 0000 0000 0000 0000 0000

显然这里有33个二进制为,发生数据溢出,而数据溢出保留低位,只留下了

0000000000000000000000000000000

答案为0

所以转化为补码形式可以使加减法统一处理

整形的在内存中的存储方式

 

计算机通常有上图这两种存储数据的方式

 

如上图采用的就是小端存储方式,注意在右图内存窗口中,左边为地址低位,右边为地址高位。

之所以右图看起来很违和,是因为我们讨论的是字节的顺序,而不是二进制位的顺序,int 的四个字节中从高位到低位分别为  00   00   00  14

按照小端存储方式,14先放在内存低位,再依次放入00 00 00,就形成了

14 00 00 00  的存储模式

大小端存在的原因,如下图:

 

2.不同类型的取值范围

以unsigned char  和char   为例

char

 

如上图,正数的最大值011111111很容易理解

但是负数的最小值比较难理解

存在疑惑的地方就是为什么100000000是-128

其实系统识别到100000000就会直接认为他是-128,原因如下

 

unsigned  char

无符号为,最大值为11111111,即255,最小值为0.

3.浮点数的存储

 

 

 

浮点数的存储较为复杂,首先我们要按照规定对它进行拆分为      

(-1)^S*M*2^E      (2是由于转化为二进制)

以  5.5为例,5.5可以表示为二进制为101.1,所以拆分为

(-1)^0  *  1.011 *  2^2       

因此在  5.5  中,S为  0,M为  1.011,E为  2   

S的存储

在内存中进行存储时,首先应该存储S,其实S可以看做浮点数的符号位

S=0时为正数,S=1时为负数,且S只有这两个可能数。

E的存储

从上表可以看到,在  float  和  double  中S都只占一个bit位   

接下来存储的是E,存入E之前必须把它加上一个数,float中是127

double中是1023,有意思的是float中E占8个bit位    而127二进制为7个1

即(1111111),只要加1就是8个bit位,所以我认为加127,是为了满足8个bit的存储方式,  而double中E占11个bit位,1023恰巧为10个1(1111111111)

讲到这里,我们继续E的存储,由于E=2,

若为float,存储时E=129,为10000001

若为double,存储时E=1025,为10000000001

M的存储

再来说M的存储方式,由于是二进制计算的M,所以M的首位一定为1,所以为了节省一位有效数字,将首位1省略,取出时会自动添上这个1

继续5.5的存储,5.5的M为1.011,省略后为011,由于本来就是二进制,所以直接存储

但是M占据的bit位有点长,在float为23位,在double为52位

所以float中为   011 0000 0000 0000 0000 0000

在double中为   

011 0000000000000000000000000000000000000000000000000

最后的拼装

最后把他们拼装起来,5.5的存储方式为

float:0100 0000 1011 0000 0000 0000 0000 0000

double:01000000 00010110 00000000 00000000 00000000 00000000 00000000 00000000

4.浮点数的取出

浮点数的存储较为麻烦,那么浮点数的取出也存在一些情况

问题主要在E的取出,因为它是要减127或者1023的

E的取出有三种情况

1.不为全0全1——正常情况

2.为全0

3.为全1

解决方法如下

E为全0时,那么原来的E为-127,那么这个数非常非常小,非常接近0

这个时候我们还原M不再添上原来的1而是直接表示成0.xxx

然后E这个时候为float(1-127),double(1-1023),

举一个例子,0 00000000 01100000000000000000000

这个数为float 直接取出M的0.11

答案为0.11*2^-126(符号位为0,数字为正)

E全为1时,表示一个无穷大的数,正负取决于符号位

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值