一、数据类型的介绍
1.整形家族
(1)char--字符型
单位:一个字节,包括unsigned char和signed char
(2)short--短整形
单位:两个字节,包括unsigned short[int]和signed short[int]
(3)int--整形
单位:四个字节,包括unsigned int和signed int
(4)long--长整型
单位:4/8个字节,包括unsigned long和signed long
2.浮点型家族
(1)float--单精度浮点数
单位:四个字节
(2)double--双精度浮点数
单位:八个字节
3.构造类型
(1)数组类型
(2)结构体类型struct
(3)枚举类型enum
(4)联合类型union
4.指针类型
(1)int *pi--整形指针
(2)char *pc--字符型指针
(3)double *pf--双精度指针
(4)void *pv--空类型指针
5.空类型
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型
二、整形数据在内存中的存储方式
前言:整形在内存中存储的是补码的二进制序列(在初阶C语言的操作符1中有详解介绍原、反、补码)
1.原、反、补码
(1)概念介绍
整数的二进制表示形式有原码、反码和补码三种,对于有符号的数据类型来说,这三种表示方法均可以分为符号位和数值位两部分,第一位数字(最高位)表示符号位,不差于数值大小的表示,正数用0表示,负数则是用1表示。若是无符号数据类型,则没有符号位,每一位都参与数值的表示。
(2)原码
直接将数值按照正负数的形式翻译成二进制就可以得到原码,有多少个比特位就有多少位二进制位。正数的原码、反码和补码都相同;但是负数则需要更具下面的定义去计算。
(3)反码
将原码的符号位不变,其他位依次按位取反就可以得到反码
(4)补码
反码 +1 就得到补码。
2.补码在内存中的存储方法
(1)使用补码存储的意义
官方定义:
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理( CPU 只有加法器 )此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。
民间定义:方便转换和计算,如计算1-1的时候
(2)存储顺序
一个内存单元为一个字节,一般数据在内存中的显示形式都是十六进制,四个二进制数字=一个十六进制,八个二进制=一个字节。
代码:
#include<stdio.h>
int main()
{
unsigned int a=-10;
int b = -10;
return 0;
}
数据在内存中的表示图:
分析图:
为什么在内存中的存储顺序是反着的呢?所以下面的大小端介绍会告诉你答案!
3.大小端介绍(*)
(1)官方定义
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位 , ,保存在内存的高地
址中。
(2)大小端民间定义
引出概念:
大小端的存储顺序是由编译器决定;而且对一个字节的数据没有作用
(3)简单实例操作
代码:
#include<stdio.h>
int main()
{
int a = 0x11223344;//十六进制数字
return 0;
}
数据在内存中存储:
(4)实战练习
题目:设计程序判断该机器的字节序
代码:
#include<stdio.h>
int main()
{
int a = 1;
char* p = (char*) //只能访问一个字节
if (*p == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
运行结果:
4.数据的存储与打印(*)--char类型
前言:我们已经知道了整形数据是以二进制的补码在内存中存储的,接下来我们更进一步了解他的打印方式(包括有符号和无符号的深度刨析),前面在操作符2中我们已略微了解到了一种方法:整形提升。
(1)char类型存储整形范围
引例:
#include<stdio.h>
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("a=%d\nb=%d\nc=%d\n",a,b,c);
return 0;
}
运行结果:
为什么同样都是存储-1,结果却大相径庭呢?接下来让我们走入char类型的世界
char类型大介绍:
首先,char内存占一个字节,一个字节=8个bit,所以就只能存放8个二进制位,所以可以存放的数据大小有范围。
对于signed char(有符号的char):
对于unsigned char(无符号char):
现在你已经知道了char类型的范围,接下来一起进入实战模拟吧。
(2)实战模拟
(1)实战1
#include<stdio.h>
int main()
{
unsigned char a = -1;
char b = 128;
char c = 128;
printf("a=%d\nb=%d\nc=%u\n",a,b,c);
return 0;
}
运行结果:
结果分析:
第一步:分析存入各个变量中的数据
第二步:分析打印的过程
(2)实战2
#include<stdio.h>
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
return 0;
}
运行结果:
(3)实战3
#include<stdio.h>
int main()
{
char a[1000];
int i;
for(i=0;i<1000;i++)
{
a[i] = -1 - i;
}
printf("%d",strlen(a));
return 0;
}
运行结果:
三、浮点型数据在内存中的存储方式
浮点数其实就是小数,精度越高,小数的位数越高。浮点数也是以二进制的形式存储的,但不是像整形数据一样以补码的形式存储。
1.认识浮点数
(1)浮点数类型分类
float---单精度浮点数
double---双精度浮点数
long double---长精度浮点型
(2)浮点数形式
直接形式:3.14159
科学计数法的形式:1E54==1.0*10^54
2.浮点数转换规则
(1)定义(表示规则)
自我描述:任何一个二进制浮点数V都可以这么表示
(2)浮点数的二进制表示
例如:十进制的:10.5;转化成二进制:1010.1
(3)思路分解
十进制:10.5
二进制:1010.1
转换成浮点数表示形式:V=(-1)^S*M*2^E
3.浮点数存储规则
弄清楚了浮点数是怎么转换成二进制的,接下来了解二进制浮点数是怎么存到内存中的。
(1)存储位序
根据公式:V=(-1)^S*M*2^E。我们只需要将S、M和E存入内存中即可(以二进制存入)
图示:
32位:
64位:
(2)规定
4.浮点数取出规则
取出的时候注意两点,第一个就是M的值;重要的是第二个,取出时,指数E有三种情况(因为存进去的时候加了一个中间值),这些都是指在内存中的E。下面逐一介绍。
(1)E不全为0不全为1(常规情况)
这种情况比较简单,直接还原就可以。
(2)E全为0
当存在内存中的E为0时,说明存入前指数E为-127(或-1023),表明此浮点数是一个特别小的数字。
(3)E全为1
当内存中的E为全1的时候,说明原值是一个极大的值,趋于无穷。
这时,如果有效数字M全为0,表示±无穷大,正负取决于S。
5.实例与错误案例
(1)代码展示
#include<stdio.h>
int main()
{
int n = 9;
float* p = (float*)//将n的地址赋予p
printf("%d\n",n);
printf("%f\n", *p);
*p = 9.0;//通过指针修改n的值
printf("%d\n", n);
printf("%f\n", *p);
return 0;
}
结果展示:
为什么会有作业的结果呢?这正是由于整数和浮点数的存储方式和取出不一样
(2)结果分析