目录
1.数据类型介绍
1.1类型的基本归类
①整形家族
int : unsigned int、signed int
char :unsigned char、signed char
short:unsigned short [int]、signed short [int]
long : unsigned long [int]、signed long [int]
②浮点数家族
float
double
③构造类型
⑴数组类型
⑵结构体类型 struct
⑶枚举类型 enum
⑷联合类型 union
④指针类型
★int *pi
★char *pc
★float *pf
★void *pv
⑤空类型
void表示空类型(无类型)
通常用于函数的返回类型,函数的参数,指针类型
2.整形在内存中的存储
2.1原码、反码、补码
计算机的整数有三种2进制的表示方法,即原码、反码和补码
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”
正数的原码、反码、补码相同,所以主要介绍负数的三种表示方式
①原码
直接将数值按照正负数的形式翻译成二进制就可以得到原码
②反码
将原码的符号位不变,其他位依次按位取反就可以得到反码
③补码
反码+1就可以得到补码
示例
正数10
原码:00000000 00000000 00000000 00001010
反码:00000000 00000000 00000000 00001010
补码:00000000 00000000 00000000 00001010
负数-10
原码:10000000 00000000 00000000 00001010
反码:11111111 11111111 11111111 11110101
补码:11111111 11111111 11111111 11110110
注:对于整形来说:数据在内存中存放的是补码。
2.2大小端介绍
既然知道整形在内存中存放的是补码,那么具体是如何存放的呢,为什么出现图片这样倒放的现象呢?【在VS2019的环境下】这就需要引入大小端这一概念了
(1) 什么是大小端:
①大端(存储)模式,是指数据的低位保存在内存的高地址,而数据的高位,保存在内存的低地址中
②小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。
(2) 为什么会有大端和小端之分呢
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应这一个字节,一个字节为8个bit,即2个16进制位。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多字节安排的问题,因此就导致了大端存储模式和小端存储模式
(3)写个函数判断大小端
#include<stdio.h>
int main()
{
int a = 1; //a的补码:00 00 00 01
char* pa = (char*)&a;
//小端存储 01 00 00 00——读出来值为1
//大端存储 00 00 00 01——读出来值为0
if (*pa == 1)
printf("小端存储\n");
else
printf("大端存储\n");
return 0;
}
3.浮点型在内存中的存储
上文中已经介绍了整型在内存中的存储,那么浮点型在内存中是如何存储的呢?
3.1 一个例子
#include <stdio.h>
//以下代码会出现什么现象呢?
int main()
{
int n = 9;
float* pn = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pn的值为:%f\n", *pn);
*pn = 9.0;
printf("n的值为:%d\n", n);
printf("*pn的值为:%f\n", *pn);
return 0;
}
最终我们实现这个函数的时候发现如下现象,那么为什么会这样呢?
3.2浮点数存储规则
为了更好的理解这个现象,我们一定要清楚浮点数在计算机内部的表示方法
根据国际表针IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:
@(-1)^S*M*2^E
@(-1)^S表示符号位,当S=0时,V为正数;当S=1时,V为负数
@M表示有效位数,大于等于1,小于2
@2^E表示指数位
eg:5.0——(-1)^0*1.01*2^2 S=0,M=1.01,E=2
-0.5——(-1)^1*1.0*2^(-1) S=1,M=1.0,E=-1
IEE745规定
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M
对于64位的浮点数,最高的1位是符号位s,接着的11位是指数E,剩下的52位为有效数字M
注:IEEE745对于有效数字M和指数E,还有一些特别的规定
①对于有效数字M而言,由于M这个数的第一位总是1,因此可以被省去,只保存后面的部分,比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
②对于指数E,情况就较为复杂。首先E是一个无符号整数。这意味着,如果E为8位,它的取值范围为0-256;如果E为11位,它的取值范围为0-2047。但是我们知道科学计数法中的E是可以出现负数的,所以IEEE754规定,存入内存是E的真实值必须再加上一个中间数,对于8位的E而言,这个中间数是127;对于11位的E而言,这个中间数是1023。
比如2^10的E是10,所以保存为32位浮点数时,必须保存乘10+127=137,即100001001.
然后指数从内存中取出还分成三种情况
⑴E不全为0或不全为1:这时候就将内存中E的值减去相应的中间数就可以得到真实值
⑵E全为0:这时候有效数字M 不再加上第一位的1,而是被还原为0.xxxxxx的小数。这样是为了表示±0,以及接近于0的很小的数字
⑶E全为1:这时候有效数字M全为0,表示±无穷大(正负取决于符号位)