- 一 、数据类型的介绍
- 1、数据类型的简介
- 2、对类型归类
- 2、为什么要将整型和浮点型这两种数据类型细化出好几种呢?
- 3、数据类型的意义
- 4、各整型能够表示的数的范围有多大?
- 二、整型向内存存放时,存放的是什么?
- 1、为什么要存放补码?
- 2、介绍二进制的原码反码和补码
- 四、在向内存存放整型的补码时,存放的顺序是怎样的?
- 五、整型的练习题
- 六、数据类型中的浮点型在内存中是如何存储的?
- 七、浮点型的练习题
- 八、向内存存放时,要占用的空间大于申请的空间怎么办?
2、对类型归类生活中,整数是一个数的类型,小数也是一个数的类型,整数和小数都是用来描述一个数的,数据类型是C语言从现实生活中抽象出来的,C语言中的数据类型也是用来描述一个数的。
刚开始学数据类型会对数据类型比较陌生,平时要多思考,多揣摩,数据类型就是数的代表,是用来描述数的。和生活中的整数是一个意思。
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
2、为什么要将整型和浮点型这两种数据类型细化出好几种呢?整型分为无符号整型和有符号整型,一般默认为有符号整型,例如int就是signed int ,但char型不固定,C语言没有规定char是signed char还是unsigned char,在大多数编译器里面是signed char。
无符号整型描述的是一个数没有符号,没有正负号,那这个数就默认为正数,正数的原反补码都相同,在通过原码计算正数的时候,原码表示的数没有符号,所以此时的原码中没有符号位,全是有效位,全部都可以参与运算;有符号整型描述的是一个数有符号,有正负号,那这个数有可能是正数也有可能是负数,如果是正数,正数的原反补码都相同,在通过原码计算正数的时候,由于原码表示的正数是有符号的,所以此时的原码中最高位是符号位,不能参与运算;如果是负数,正数的原反补码不相同,补码取反+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
构造类型:
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
指针类型:
int* pi
char* pc
float* pf
void* pv
这里是引用
上面我们说了,数据类型是从生活中抽象出来的,生活中有整数,小数和字母,那只抽象出三种就可以了,为什么还要对整型进行划分,对浮点型进行划分呢?
3、数据类型的意义答: 不同的数据类型能够代表的数的范围不同,在表示数的时候,选择合适的数据类型,用来表示不同的数,能够增加空间的利用率,减少空间的浪费。
打个比方说:数据类型就像酒店房间的类型,给房间规定好哪个房间是单人间,哪个房间是双人间,三人间,如果一个客人来住,那就给他安排单人间就可以,安排双人间和三人间就是浪费了。
4、各整型能够表示的数的范围有多大?数据类型决定了两个方面:
第一个方面:数据类型就像变量的主人,它控制着,决定着变量能够向内存申请多大字节的空间,如果一个变量的类型是short类型,变量就能够向内存申请2个字节的空间,如果一个变量的类型是int类型,变量就能够向内存申请4个字节的空间。
第二个方面: 数据类型决定着我们看待内存空间的视角,也就是决定着我们会认为内存空间放的是什么,如果一块内存空间对应的变量类型是int类型,那我们,计算机等等,都会认为里面存放的是int类型的值,如果一块内存空间对应的变量类型是short类型,那我们,计算机等等等,都会认为里面存放的是short类型的值。
打个比方:如果一个瓶子上写着可口可乐,我们就会认为里面是可乐,如果一个瓶子上写着雪碧,我们就认为里面是雪碧,如果一个瓶子上写着白开水,我们就认为里面是白开水。
%d和%u的区别:
使用%d时,我们会认为内存里面存放的是有符号的整数,整数有可能是正数也有可能是负数,表示整数的二进制数的最高位是符号位,如果符号位是1,则是负数,求负数时,要根据原码求,内存中放的是补码,负数的原反补都不相同,对补码取反,+1,求得原码,再求负数。如果符号位是0,则表示正数,求正数时,也要根据原码求,内存中放的是补码,而正数的原反补都相同,直接根据补码,求得了正数。
使用%u时,我们认为内存里面存放的是无符号的数,则是正数,表示正数的二进制数中没有符号位,全是有效位,求正数的时候,内存中放的是补码,需要根据原码求正数,正数的原反补都相同,直接根据补码求得正数。
二、整型向内存存放时,存放的是什么?类型是描述数的,并且规定了每种类型创建的变量能够占用多少空间,char类型是用来描述字符的,但向通过char类型创建的变量里面存的是字符的ascii值,ascii值是整数,所以char类型也属于整型,规定char类型的变量占用1个字节的空间,所以能够存放8位二进制数,则总共能够存放二进制数的组合为00000000-11111111这些数,char类型分为signed char和unsigned char,signed char是有符号的字符型,使用这个类型创建的变量,我们认为里面存放的数是有符号的数,则里面存放的数的二进制数的最高位是符号位,如果是0,就是正整数,如果是1,就是负整数,00000000-01111111代表的都是正整数,代表的数的范围是0-127,10000000-11111111代表的都是负整数,代表的数的范围是(-128)-(-1),所以signed char类型的变量的取值范围是-128到127。
unsigned char是无符号的字符型,使用这个类型创建的变量,能够存放8位二进制数,则总共能够存放的二进制数的组合为00000000-11111111,我们认为内存里面存放的是没有符号的数,也就是正数,则里面存放的用来表示数的二进制数没有符号位,全是有效位,则00000000-11111111这些二进制数表示的数都是正数,则正数的范围是0-255,所以通过unsigned char创建的变量的取值范围是0-255。
1、为什么要存放补码?整型向内存存放的时候,存放的是它的二进制形式的补码。
计算机只认识0和1,所以就向内存存放二进制形式的整数,整数的二进制的表现形式又分为原码,反码,和补码。
因为原码是正宗的,反码和补码是变换出来的,所以就有了这个疑问,为什么不放原码,这个正宗的进去,而是放整数的补码进去。下面三点原因,进行了解释:
2、介绍二进制的原码反码和补码第一点:原码不够忠心,它的符号位不能参与运算,将补码存放进去,在参与运算的时候,补码的符号位也可以参与运算,而原码就不行。
第二点:原码的能力有限,使用补码可以进行加减法的运算,而原码不能进行减法的运算,cpu只能进行加法的运算,当有减法的运算时,计算机只能将减法转化为加法的形式,转化形式之后,对原码计算之后,不能得到正确的结果,只有补码才可以得到正确的结果。
第三点:通过补码得原码非常简单,两者的转换过程是一样的,如果补码的符号位是1,表示的整数是负数,最后想要得到原码,直接对补码取反,+1,就可以得到,非常方便,不需要额外的硬件电路。
注意:存放的是二进制数,但为了表示方便,在显示内存中存放的数字时,显示的是16进制的,用四位二进制数表示一位16进制,因为16进制最大能表示的数是15,15用四位二进制数表示,所以16进制在表示二进制时,统一用一位16进制表示四位二进制数。献祭四位二进制数才能得到一位16进制数。
四、在向内存存放整型的补码时,存放的顺序是怎样的?这些进制都是数值的表现形式,就比方说将数值比喻为孙猴子,他有81种形态,但每一种形态都表示孙猴子,而数值呢,进制就是它的表现形式,每一种进制都表示这个数值。
二进制也是用数值的表现形式,二进制在表现数值的时候,有三种表现方法,分别为原码,反码和补码。
这三种表现方法都分为符号位和数值位,最高位是符号位,表示正数时,符号位是0,表示负数时,符号位是1。
根据二进制求十进制时,只能通过原码求十进制的数,原码是正宗的,反码和补码是变换得来的。
正数的原码,反码和补码都相同,正数比较惨,只有一种二进制序列可以表示它。
负数的原码,反码和补码都不相同,原码取反得到反码,反码+1得到补码。
存放的顺序有两种,一种是正着存放进去,也就是原封不动,直接放进去,另外一种是倒着存放进去,就是对数据调个头。然后放进去,分别给这两种方式取的名字是大端字节序存储和小端字节序存储。字节序的意思是以字节为单位,讨论他们存放的顺序。
其实存放的顺序有好多种,补码作为一串二进制数,设置有一个字节大小的二进制数为一组,那这一串二进制数就可以分成好几组,这好几组在向内存存放的时候,有很多种顺序,但是只要记住存放的顺序,在拿出来的时候,也就是在使用的时候,因为在使用的时候,必须要拿出来才能使用,根据存放的顺序拿出来就行,但计算机要记住这些顺序太麻烦了,所以就只保留了两种存储简单的顺序,一种正着存放,一种倒着存放。
下面具体介绍这两种方式:
这里我们说内存空间的地址左到右是低地址到高地址,数据的二进制数从左到右是高位到低位,头是高位,尾是低位。
第一种: 将二进制数的低位保存在高地址的内存空间,二进制数的高位保存在低地址的内存空间,原封不动直接存放进去,这种存储形式就是正着存放的,就叫做大端字节序存储。
第二种: 将二进制数的低位保存在低地址的内存空间,二进制数的高位保存在高地址的内存空间,这是倒着存放的,就叫做小端字节序存储。
画图理解:
大端存储:
小端存储:
练习题:使用C语言判断当前机器的存储顺序是大端还是小端
这个问题其实和生活中如何判断一个人是左撇子还是右撇子是一个问题,那如何去判断这个人呢?就是让这个人左一件事,看他使用的是哪只手,就知道他是左撇子还是右撇子,所以这个问题也是一样的,要想知道机器存储顺序是是大端还是小端,就让机器,去存储一个数,再看这个数是如何存放的,如果这个数的二进制数的低位放在了他所占用的空间的第一个字节处,那他就是倒着存放进去的,就是小端存储顺序,如果这个数的低位没有放在他所占用的空间的第一个字节处,那他就是正着存放的,就是大端存储顺序。
所以我们使用了一个非常简单的数1,就可以判断出来。
具体的思路是:取出1所占用的空间的第一个字节大小的空间的地址,对地址解引用找到空间的值,如果值是1,则为小端,如果是0,则为大端。
#include五、整型的练习题int main() { int a = 1; char* p = (char*)&a; if (*p == 1) { printf("小端字节序存储n"); } else if (*p == 0) { printf("大端字节序存储n"); } return 0; }
1、
//输出什么? #includeint main() { char a= -1; signed char b=-1; unsigned char c=-1; printf("a=%d,b=%d,c=%d",a,b,c); return 0; }
思路:
1:向内存存放
2:打印
1: 字符型a的空间只有1个字节的大小,只能存放8位二进制数,而-1是整型,要占用4个字节的空间,要存放32位二进制数,所以只能将-1的补码的低八位存放到a里面,这种形式叫做截断。
打个比方说:要将2米的棍子放到只能存放1米的背包里面,只能将2米的棍子截断,然后放到背包里面。
2:存到里面之后,要打印有符号的整型的a
打印分两步:
第一步:对a整型提升
对a整型提升,提升到整型,整型占32个比特位的空间,存放32位二进制数,而a里面只有八位,此时a的类型是有符号的字符型,所以计算机会认为a里面存放的是有符号的数,a里面放的是有符号数的补码,符号位是最高位,符号位是1,则补1,补全32位,如果a的类型是无符号的字符型,所以计算机认为里面存放的是无符号的数,这个数数的补码没有符号位,全是有效位。
第二步:打印的是有符号的,所以计算机会认为里面存放的有符号的数,补码的最高位应该是符号位,符号位是1,则里面存放的是负数,对补码取反,+1得到原码,就可以得到10进制的数,最后打印的是这个10进制的数。
画图理解:
2、
#includeint main() { char a = -128; printf("%un",a); return 0; }
3、
#includeint main() { char a = 128; printf("%un",a); return 0; }
4、
int i= -20;
unsigned int j = 10;
printf("%dn", i+j);
5、
unsigned int i;
for(i = 9; i >= 0; i--) {
printf("%un",i);
}
6、
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0; }
7、
#include六、数据类型中的浮点型在内存中是如何存储的? 七、浮点型的练习题 八、向内存存放时,要占用的空间大于申请的空间怎么办?unsigned char i = 0; int main() { for(i = 0;i<=255;i++) { printf("hello worldn"); } return 0; }
例如
char a = 10;
10是整型,它的二进制数有32位,占用4个字节的空间,char类型的变量只能向内存申请一个字节的空间,也就是只能存放8位二进制数,所以只能对10的二进制数进行截断,存10的二进制数的低八位。



