前言
1. 数据类型介绍
这里链接已介绍了基本的内置类型以及它们所占内存空间的大小
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
复习一下类型存在的意义:
1.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
long double
构造类型(自定义类型):
> 数组类型
> 结构体类型 struct
> 枚举类型 enum
> 联合类型 union
例如
指针类型
int *pi;
char *pc;
float* pf;
void* pv;
空类型:
2. 整形在内存中的存储
我们之前讲过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
2.1 原码、反码、补码
计算机中的整数有三种表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,正整数三码相同,所以以一代三;而负整数的三种表示方法各不相同。正负整数都以补码的形式储存在内存中,而它们实际的值由原码转换而来,所以要得到负数的值,首先要得到补码,然后再算反码,最后得到原码。
原码
反码
补码
对于整型数据来说:数据以补码的形式存放在内存中,Why?
不得不佩服早期的计算机科学家能想到用反码补码。
对于以下代码,我们查看它们在内存中的存储:
int a = 20;
int b = -10;
如果是刚学会二进制的同学,不妨将a和b的值转化为32位的二进制编码吧,它们的16进制编码分别为:0x 00 00 00 14
,0x ff ff ff f6
一直有个疑问,为什么这里的地址是倒过来的呢?但又不是整个,而是两个一对地倒?
且看下面的讲解吧!
2.2 大小端介绍
什么是大小端:
为什么会有大端和小端呢?
2.2.1 大小端例子
int a = 0x11223344;
▶图解
2.3 练习
2.3.1
思路:
优化:
怎么只取一个字节比较呢
理清思路:
代码呈现:
//代码1
#include <stdio.h>
int check_sys()
{
int i = 1;
return (*(char *)&i);
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
2.3.2
//输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
先思考,再往下看
变量的类型,打印的格式?
结果:
对a
分析:
对c
分析:
体会
3. 浮点型数据在内存中的存储
常见的浮点数:
3.1 举个栗子
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
结果:
暂且把问题放在这,稍后再看。
3.2 浮点数存储规则
num
和*pFloat
在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别这么大?
要理解这个结果,一定要搞懂浮点数在计算机内部的表示方法。
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V
可以表示成下面的形式:
举例:
小结:
IEEE 754规定:
IEEE 754对有效数字M和指数E,还有一些特别规定。
至于指数E,情况就比较复杂。
然后,指数E从内存中取出还可以再分成三种情况:
E不全为0或不全为1
E全为0
E全为1
小结
4. 取出规则
4.1 E不为全0或不为全1
4.2 E全为0
4.3 E为全1
5. 重新分析第一题
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
结果:
- 对于前两行(第二行)结果
- 对于后两行(第二行)的结果
**补:储存M值的时:去掉小数点前的1,如果小数点位数用完了,补0**