- C语言里面没有字符串类型
- 布尔类型(_Bool)(C99引入)专门用来表示真假,但是在C语言中不需要布尔类型也可以表示真假
char也属于整形(每一个字符在储存的时候是储存他所对应的ascll值,ascll是整数)
有一些变量只有正数由意义,例如年龄,价格。定义这些变量的时候就可以用无符号数定义 ,无符号数只能存储正数。
//无符号变量只能储存正数
//即使这里输入了一个负数,它也会把这个负数转化成一个正数(不是简单的去掉符号,这是关于二进制的计算)
对于有符号数字和无符号数字的打印
打印无符号数应该用%u
%u和%d打印的解读方式不同:
- 使用%d 时,会认为这是一个有符号数,打印的时候会认为二进制中第一位是符号位;
- 使用%u时,会认为这是一个无符号数据,会认为整个二进制序列都是有效位。
//如果存储了一个-10进去会怎么样
//会打印,而这个数据不是随机数
为什么无符号整形储存 -10 的时候会打印出来(并不是随机数)?
%u在解读的时候认为此时a仍然存储的是正数,解读了a的补码。在本章后面介绍原反补吗的时候在详细解释细节。
构造类型(自定义类型)
void表示空类型(无类型)
通常应用于函数的返回类型,函数的参数,指针类型
然后我们观察a、b在内存中的储存
数据在内存里面是以二进制储存的,但是编译器是以十六进制展现给我们看的:
为什么是这样的值呢?下面介绍整数的原码、反码、补码。
整数二进制有3种表示形式,而内存中存储的是二进制的补码
正整数的原码、反码和补码相同
- 原码:按照一个数的正负直接写出来的二进制就是原码
- 反码:符号位不变,其他位按位取反 (并不是按位取反)
- 补码:反码的二进制序列加1
从原码转换成补码:先取反再加一。
从补码转换成原码:可以先减一再取反,也可以先取反再加一(和原码转换成补码的过程相同)。
解释为什么%u打印-10;会出现
用上面的方法我们就可以计算出-10的补码:
回到最开始使用%u打印-10会打印成,是因为在使用%u的时候,不会解读符号位,会将整个32位二进制都当作有效位,读出一个数据,而这个数据就是。
同时回到刚才a,b的值
为什么和在内存界面看到的不同呢?
内存界面和我们计算出来的顺序是相反的:
这就和字节序有关,下面我们来了解字节序
当储存的内容超过一个字节的时候,储存的时候就有顺序
(一个char类型的数据是没有字节序。char类型的数据只有一个字节,没有顺序)
机器有两种对字节的存储顺序:
低字节数据存放在高地址处,高字节数据存放在低地址处 低字节数据存放在低地址处,高字节数据存放在高地址处
我们用下面这个例子来解释:
而我在观察内存的时候发现我的机器是按照方式2进行存储的,所以我的机器是采用的小端字节序。
那么有什么方法可以快速判断自己当前使用的机器属于哪一种字节序呢?
设计一个小程序判断当前机器属于哪种字节序
//只需要判断第一个字节的内容是不是1
//强制类型转换截取了a的第一个字节
储存时数据发生截断以及整型提升
这里我们将三个相同的整数 -1 分别存进了两种类型的变量,(在我所使用的VS2019编译器下char和signed char等价),而这两种类型又都属于char类型 char 类型的变量只能储存一个字节(8个比特位)大小的数据,但是 -1 是整形(包含32个比特位),
这里就需要发生数据截断: -1 的二进制补码是11
截断:将补码的最后八位赋值给变量a、b、c。 这里需要将char类型的数据以%d的方式打印,但是%d只能解读整数数据(整数有四个字节),而char类型的三个变量都只有一个字节,所以这里会发生整型提升:
整形提升:对于有符号数据,高位补符号位,对于无符号数据:高位补0
%d打印的时候会认为这就是要打印数据的补码,按照打印正常整数的形式打印这三个变量
观察数据: -128 是一个整数,二进制有32位 : 但是接受这个数据的变量是一个char类型的变量(只能接受8个比特位)
联想:这里如果是a = 128,那么阶段后的值仍然是
打印整数(四个字节),所以这里需要发生整形提升(a是有符号char,高位补符号位)
%u的形式打印这个变量,因为%u应该打印的是无符号整数,且打印的时候认为整个32位全为有效位,
- 在浮点型数据后面加了f是float类型,不加则默认是double类型
- %f和%lf默认小数点后六位
浮点型和整形在内存中的储存方式不同
我们通过下面这个例题来探究浮点型和整形在内存中的储存方式有什么不同
为什么会出现这样的情况?
回答这个问题前,先来了解浮点型的二进制存储形式:
国际标准电气电子工程师学会(IEEE):任何一个二进制浮点数V都可以表示成下面的形式
- (-1)^S表示符号位,当S为0 时表示正数,当S为1时,表示负数
- M表示有效数字,大于等于1,小于等于2
- IEEE浮点数标准定义了两种基本的格式:以四个字节表示的的单精度格式和八个字节表示的双精度格式
单精度浮点数储存格式(32位)
双精度浮点数储存格式(64位)
IEEE754对于有效数字M和指数E有一些特别的规定:
1.我们已经知道1<=M<2,也即是说M一定可以写成这样的形式:1.xxxxxx
其中xxxxxx表示小数点后面的部分
2.在计算机内部储存M时,由于第一位总是1,所以把这个1省略,只保存后面的小数部分,这样可以节约一位有效数字,这样的话储存的数据精度就可以提升一位:例如在单精度浮点型存储格式中,最后23位作为有效位,但是储存在计算机的数据精度是24位 计算机会认为这是一个无符号数,但是十几行会存在很多E取负数的情况,所以IEEE754规定:存入内存时,E的真实值必须在加上一个中间数
,对于单精度,这个中间数(也叫做偏移量)是127,对于双精度,这个中间数是1023
例如:对于十进制的数字0.5,它的二进制是0.1,E= -1;那么我们就需要把-1在加上127得到126后,将126储存在指数位
拿出这些储存的数据(三种情乱)
情况一:E不全为0或不为全1
- E: 指数位值减去127(1023)得到真实值
- M: 有效位的数值前面加上1.
真实的E是一个十分小的数字,接近0;
这时候不用计算,E直接就等于1-127(1-1023)就是它的真实值 M不再在前面加上1,而是还原成0.XXXXXX的小数,这样做是为了表示正负0,以及接近于0的很小的数字。
- 第一组为什么以%f打印整数9,会打印出0.000000?
此时E为全0,是一个会被判定成一个十分小的数据,所以打印0.000000
- 为什么第二组中以%d的形式打印*pf时,会打印出?
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。