目录
1.数据类型的详细介绍
<1>类型的意义
1.开辟内存的大小(大小决定了使用范围)
2.如何看待内存空间的视角
<2>归类
整型家族
char 字符在存储的时候是ASCII码值,ASCII是整数,所以在归类的时候,字符属于整型家族
unsigned char无符号
signed char有符号
short
unsigned short[int] short int num
signed short[int] short num
long
unsigned long //无符号
signed long//有符号
int num=0;这种就代表有符号数
signed int num=0;
常见的编译器singed int==int
浮点数家族
float
double
构造类型(自定义类型)
数组类型
int arr[10] int arr[11]元素个数的变化,数组类型变化
char arr[10] 类型的变化,数组类型变化
结构体类型struct
枚举类型enum
联合类型union
指针类型
int *p
char *p
float *p
void *p
空类型
void表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型
以上就是对数据类型的介绍和概况
以下将针对
<1>整型类型存储(正数,负数):原码,反码,补码
<2>大小端节序的判断和介绍
<3>浮点型内存中的存储(ems)
2.整型类型在内存中的存储
原码,反码,补码
计算机中的整数有三种2进制表示方法:::::::::::::::原码——反码——补码
对整型而言:正数负数在内存中存储的是补码
正数的原反补码都是一样的
负数
-1
原码 1000000000000000000000000000001
反码 1111111111111111111111111111110
补码 1111111111111111111111111111111
在计算系统中,数值一律用补码来表示和存储。
why:
1:使用补码,可以将符号位和数值域统一处理
2:加法和减法也可以统一处理(cpu只有加法器)此外不需要额外的硬件电路
a-b=a+(-b)
3:补码和原码相互转换,其运算过程是相同的
(原码——-——补码 (都是取反加1)补码——————原码)
3.大小端的介绍和判断
20
//补码 0000 0000 0000 0000 0000 0000 0001 0100
//四个0相当于一个0
0x 00 00 00 14
-10
//原码 1000 0000 0000 0000 0000 0000 0000 1010
//反码 1111 1111 1111 1111 1111 1111 1111 0101
//补码 1111 1111 1111 1111 1111 1111 1111 1010
//四个1相当于一个1
ox FF FF FF F6
20:
-10:
a和b分别存储的是补码,顺序相反由于大小端的原因
大端:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中(低位字节数放到高地址处,高位字节数放到低地址处)
小端:是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中(低位字节数放到低地址处,高位字节数放到高地址处)
如果存储空间超过一个字节,那必定有个大小端问题,不管是字符,整型还是浮点型
所以这就是为什么导致了内存地址是反着来存储的,vs2019是以小端存储的,低字节数放到低地址处 。原来是因为大小端影响
设计一个程序来判断这部机器的字节序
只需要与低地址的第一个字节比较即可
ox 00 00 00 01
小端 01 00 00 00大端 00 00 00 01
直接取&a的地址,然后强制类型转换为char*
如果==1,则是小端,否则是大端
int check_sys()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = check_sys();
int a = 1;
char* p = (char*)&a;
if (ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
对整型(有符号和无符号)一些题目:
%u打印的是无符号的正数且是原码
%d打印的是有符号位的整数且是原码,并且十进制
unsigned 无符号位 (无符号位转化为有符号位)
高位如果是1,则提升前面都是补1
有符号char(8) -128~127
无符号unsigned char 0~255
有符号short(16)
<1>
记住:无符号数一直都是大于等于0的数,如果从9一直减直到减到0为止,之后再次减1成为-1,由于记录的是无符号整数,则-1也会理想化为1,然后导致了一直循环下去,进入了死循环,因为i--后成为负数显示依旧是正数,是unsigned无符号引起的
所以遇到unsigned 进行循环的变量,那么大多数都是进入了死循环
也可以利用这个图看,-1开始 -1 -2 -3 -4 ........-128 再减1 得 127 ......4. 3 2 1 0 -1
-1~-128 一共128个数
127~0一共127个数 相加起来是 128+127=255
<2>
记住:无符号数一直都是大于等于0的数,如果从9一直减直到减到0为止,之后再次减1成为-1,由于记录的是无符号整数,则-1也会理想化为1,然后导致了一直循环下去,进入了死循环,因为i--后成为负数显示依旧是正数,是unsigned无符号引起的
所以遇到unsigned 进行循环的变量,那么大多数都是进入了死循环
对于无符号整数,它的值永远都是>=0,所以以上的代码一直不会跳出循环,进入了死循环
以上就是对于整型数据的无符号和有符号数,大小端,整型数据在内存中存储的相关知识和题目
4.浮点型在内存中的存储
浮点数存储的规则
浮点数在计算机中内存的表示方法 (-1)^s*M*2^E(根据国际标准IEEE)
对于单精度浮点数
推导一下9.0
<1>这里的9.0对应的二进制数是 1001.0
9对应1001
eg:小数点后的代表的权值是2^-1 2^-2等等.0对应的是0,如果是.5则表示0.5=2^-1次方,9.5 写成为 1001.1
<2>由于是正数所以s=0
利用科学计数法 1001.0写成1.001*10^3 所以 e=3
m=1.001
<3>由于单精度浮点数,e所在的区域是8个字节,总共127 需要将 e+127=130 对应的二进制数是10000010
<4>m=1.001 取小数点后的数,小数点前的数如果是1则前面全部补1,反之全部补0、
001 小数点前面数是1 则前面全部补1
1000000000000000000000000000000001
然后即可算出实数在计算机中的存储方式了
<1>取出s,m,e的值
<2>关于e 如果是32位 则需将 e+2^7-1
如果是64位 则需将e+2^10-1
<3>float e的最大值是127
<4>double e 的最大值是1023
//浮点数在内存中存储的例子
int main()
{
int n = 9;
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);//9
//000000000000000000000000000001001--9的补码
//s:0 e:00000000 m:000000000000000000001001
//e为全0的时候,再之前加个0. float:e=1-127 double:e=1-1023
//(-1)^0*0.000000000000000000001001*2^-126
//无限接近于0的数 0.0000000
printf("*pFloat的值为:%f\n", *pFloat);//0.00000
*pFloat = 9.0;
//1001.0
//1.001*2^3
//(-1)^0*1.001*2^3
//s=0
//e=3
//m=1.001
//01000001000100000000000000000000000000000000000补码=原码
printf("num的值是:%d\n", n);//1091567626
printf("*pFlaot的值是:%f\n", *pFloat);//9.00000
return 0;
}
//以整型数据来解读成浮点数
//整型以补码存储,以补码来确定s e m的值
//关于e 全为0的时候 m再此之前加个0
// float:e=1-127 double:e=1-1023
// 关于e 不全为0或者不全为1时候 m前加个1
//算出v的值
//以浮点数数据来解读成整型
//浮点型提供了十进制数,转化为二进制数,弄成科学计数法,然后确定 s e m
//然后利用%d打印的是无符号整型且原码来算出十进制数