提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
主要学习整型与浮点型数据在内存中的存储方式以及相应代码分析。
一、C语言数据类型
C语言主要有四种类型:
1.基本类型:(1)整型:
①字符整型char
②短整型short
③整型int
④长整型long
⑤更长整型long long
注意:整型数据每个类型都有signed、unsigned之分
而未标明有无符号时,默认为有符号(2)浮点型:
①单精度浮点型float
②双精度浮点型double2.构造类型:
(1)数组类型
(2)结构体类型:关键字struct
(3)枚举类型:关键字enum
(4)共用体类型:关键字union3.指针类型
4.空类型:void
为何要使用数据类型?
1.数据类型决定了数据在内存中存储的方式与大小;
2.数据类型决定了看待内存空间的角度;
二、数据在内存的存储
这里主要探讨整型与浮点型数据在内存中的存储方式。
1.整型数据
(1)前提
在学习整型数据在内存的存储时,我们要先明确以下几点:
第一,整型数据有三种表达形式:原码、反码、补码;
第二,三种表现形式都由符号位与数值位组成,符号位0代表正数数,符号位1代表负数;
第三,正数原码、反码、补码相同;
第四,内存中存储的整型数据的二进制补码;
(2)原码
原码就是将一个int数据展开为32位的二进制数。
例如:
-5 ——>10000000 00000000 00000000 00000101
5 ——> 00000000 00000000 00000000 00000101
(3)反码
反码就是对原码除符号位之外的每一位按位取反得来的。
例如:
-5——>11111111 11111111 11111111 11111010
5 ——>00000000 00000000 00000000 00000101
(4)补码
补码就是反码加一
例如:
-5——>11111111 11111111 11111111 11111011
5 ——>00000000 00000000 00000000 00000101
(5)重点
①char类型的数值范围
char类型只占一个字节(8个bit)
unsigned char:0-255也就是11111111
signed char:-128-127
其取值变化范围为:
②整型提升与截断
什么是整型提升?
整型提升就是在进行整型运算时,将字节数小于int字节的数据类型(short或者char)转化为整型(int)类型。
为什么要进行整型提升?
因为在计算机中运算都是有CPU中的运算器ALU完成的,而ALU在设计时被规定,其操作对象的大小至少是int类型;与此同时,ALU的操作对象是存储在内存中的寄存器上,而计算机的通用寄存器的字节大小是与算术逻辑单元(ALU)保持一致的。所以这就要求对于short或者char类型的数据进行整型运算时,要先将它们整型提升为int。
如何进行整型提示?
对于有符号的数据类型,我们需要在其二进制补码前补符号位,直到将8个bit位的char数据补成32个bit位,或者16个bit为的short类型补到32个bit位;
对于无符号的数据类型,我们需要在其二进制数前补0,直至补齐32个bit位;
截断:
截断就是在将整型数据存入short或者char类型变量中时,只存放16、8个bit位,去除其它位。注意所保留的位数是从二进制的数值低位开始数。
(6)例题
char a = 255;
unsigned char b = -1;
printf("a = %u\n", a);
printf("b = %u\n", b);
分析过程:
第一行:255的二进制原码(补码)1111 1111,变量a是有符号的char类型,将255的补码存入a中。因为a有符号,故第一个1是符号位,此时a代表的数值要进行补码到原码的转化,即1000 0001,所以a中数值是-1;
第二行:-1的二进制补码是1111 1111,变量b是无符号的char类型。所以求a中数值时,八个bit位都是数值位,而且没有原码补码的区分,故b中数值是255;
第三行:打印涉及整形运算,先将a进行整型提升,a中存放1111 1111,且a是有符号的,故在高位补符号位1,得到11111111 11111111 11111111 11111111,又以无符号形式打印,所以该二进制没有原码补码的区分且全是数值位,打印得到极大的数:4294967295;
第四行:将b进行整型提升,b中存放1111 1111,且b无符号,直接在高位补0,得到00000000 00000000 00000000 11111111,又以无符号形式打印,所以该二进制位都是数值位,且原码补码不区分,打印得到:255
结果:
char a = 255;
unsigned char b = -1;
printf("a = %d\n", a);
printf("b = %d\n", b);
分析:
第一行:同上;
第二行:同上;
第三行:a进行整型提升,且a是有符号的,故在高位补符号位,得到11111111 11111111 11111111 11111111,以有符号的形式打印,因为首位是1,所以是负数,要将二进制补码转为原码,得到10000000 00000000 00000000 00000001,所以打印得到:-1;
第四行:b进行整型提升,且b无符号,故在高位补0,得到00000000 00000000 00000000 11111111。以有符号的形式打印,因为首位是0,所以是正数,原码补码一致,打印得到:255;
结果: