一、首先我们要了解计算机对数据的存储
- 全部数据都是已经用二进制来存储,但是整数是直接存储,浮点数分为整数部分和指数部分分开存储
- 但是VS的内存中是用十六进制来表示对二进制的存储。并且用两位十六进制数表示八位二进制数。这样可读性更高,也节约显示空间
- 但是想要弄清这个概念,我们可能要搞懂字节、字、bit、byte的关系和区别。其中位是bit,比特,表示二进制位。1字节是8位(1byte=8bit),一字(1word=2byte)是两个字节。字长是字的长度,一个字的字长是16,一个字节是字长是8,并且字节是计算机中最小的存储单位
- 那么在vs内存中的十六进制代码,每个“两位数”都代表一个字节。并且我们可以看出来,在内存中的存储是从最低位的字节开始放起,但是由于字节是最小的存储单位,字节内部顺序不变。
- 二、我们用下面的简单代码来验证,为了在内存中找到变量,我们设置一个数组并且将数组推进内存,在变量的赋值过后内存中会出现红色字体,就是该句变量赋值的句子
-
#include <stdio.h> int main(void) { char e[40]; int a = 12345678912; double b = 12345678912.99; double c = 10000000000.78; int d = 234556789; printf( "Hello,%d\n",a); printf("Hello,%f\n", b); printf("Hello,%f\n", c); printf("Hello,%d\n", d); return 0; }
打开调试,设置断点。
- 如图,在运行完int a=12345678912时,40 1c dc df就是实际储存进变量a的值。此时下面的局部变量窗口显示a的值变成-539222976。用计算器的程序员模式我们发现输入十进制的12345678912,变成十六进制是2 DFDC 1C40。可以看出来顺序是按字节反着出现的,由低位开始放起。并且由于int类型只能有四个字节,最高位的2溢出,无法存入。
- 我们来复习一下C语言中不同数据类型占用的内存:
-
int 基本整数类型,C语言规定不小于十六位,在vs中是四个字节32位
char 1字节,8位;short 2字节 16位。int、long和float类型都是四个字节。long long和double都是八个字节。
-
接下来还要涉及的一个问题就是浮点数的溢出,在这里我们只讨论我们把b改成float类型进行验证。我们在这里只讨论尾数溢出
-
int main(void) { char e[40]; int a = 12345678912; float b = 12345.1117; double c = 10000000000.78; int d = 234556789; printf( "Hello,%d\n",a); printf("Hello,%f\n", b); printf("Hello,%f\n", c); printf("Hello,%d\n", d); return 0; }
- 我们首先要明确一个有效数字的概念:在浮点数中,有效数字是整数部分和小数部分一共的位数。对float来说,有效数字是6-7位。double是15位。因此float a;a=12345.6789,只能存储12345.67,最后两位丢失。在vs中变成12345.6787,存储12345.67894567,变成12345.6787。我们可以看出来在有效数字范围内的部分是一直保持精确的,但是在有效数字外会有四舍五入或者自己出现的数字。因此浮点数是不精确的,在你给出的数字外可能出现随机数字,有时候if(a==0.0)作为判断条件会无效。
- 该图中d虽然是在有效数字之内,但是由于自动生成,造成浮点数实际数值和程序中数值不同。体现浮点数不够精确。
- 在默认情况下以%f格式输出的情况下会输出6位小数,但并不能保证这6位小数有效,即:是否有效还要看整数位和小数位加在一起是否超过7位。例如另外我们要知道:有效数字的位数与指定输出的小数位数(%.7f)是两码事。%.mf 格式是自己设置需要输出几位小数。
例如图中就是实际变量和输出的区别。并且printf函数具有自动四舍五入的功能。有的时候如果给出溢出的数值,在实际的变量存储中也会出现类似四舍五入的情况,但是实际上这个值是不准确的。
- 在默认情况下以%f格式输出的情况下会输出6位小数,但并不能保证这6位小数有效,即:是否有效还要看整数位和小数位加在一起是否超过7位。例如另外我们要知道:有效数字的位数与指定输出的小数位数(%.7f)是两码事。%.mf 格式是自己设置需要输出几位小数。