目录
一.C语言中的数据类型
(1)整型家族(char , short ,int , long)
(2)浮点型家族(double , float)

图来自菜鸟教程网站
(3)构造类型
(4)指针类型(int* , void * , char * , float*)
(5)空类型(void)
1.函数返回为空 (比如一个简单的打印函数,就不需要返回值,不返回值的函数返回类型即为空)
2.函数参数为空,有些函数,不接受参数,则参数类型可以设置为空
3.指针类型为void *,该类型指针无法解引用,无法进行指针运算,但它可以根据我们的需求,转化为任意数据类型.
二.整数的存储方式
1.原码,反码,补码
(1)补码出现的原因:
数字在计算机中是以二进制的方式进行存储,区分正数或者负数是看最高位,最高位为0,则为正数;最高位为1,则为负数
假设我们用int类型(32个bit位)来存储1,-1,假设电脑中只存在原码
1
00000000 00000000 00000000 00000001
-1
10000000 00000000 00000000 00000001
由于CPU中只存在加法器,如果按照原码直接进行相加,得到的二进制,转为数字,得到的是-2,显然1-1 -2,得到的答案是错误的.
于是聪明的科学家想了一种方法,也就是原码.反码.补码的方法
通过这种方法,我们不仅实现了符号位和数值域进行统一处理,无论负数还是正数,都有唯一一个二进制与之对应转化,同时,我们通过补码,统一了加法和减法运算.
通过这种方式,我们就可以解释为什么有符号char类型,范围在-128到127之间
(2)具体实现
比如-1,这里拿一个字节存储举例
它的1原码是1000 0001,符号位不变,所有位按位取反,则它的反码是1111 1110
反码+1得到补码,也就是1111 1111,所以-1在计算机中就是1111 1111来存储的.
当然补码得到原码的另一种方式,除了逆着进行外,还可以重新按照原码得到补码的方式再重新操作一遍,非常神奇!!!
2.大小端存储
在了解正数以补码的形式存储后,我们就可以打开vs2019进行内存监视了,16的十六进制为10,在内存监视中,我们可以很好的观察到,不过为什么有点像是倒着存的?
数据的存储有如图两种存储方式, 统称为字节序存储(以字节为一个单位),像char类型一个字节大小,则完全没有大端小端这样的概念.
一种称为大端(字节序, 指数据的低位存储在高地址,数据的高位存储在内存的低地址
一种称为小端 (字节序),指数据的低位存储在低地址,数据的高位存储在内存的高地址
因此由上图在内存中的显示,我们可以知道,在目前X86环境底下是以小端字节序存储.而在我们知道的KEIL C51是大端字节序存储,有些ARM处理器,其可以通过硬件,根据自己的设置,调整是大端还是小端.
至于如何判断是大端还是小端,我们可以简单设计一个代码,1在大小端存储是不同的,我们取出1的地址(低地址),将其转为char *类型,再解引用(访问一个字节),得到1即为小端,得到0即为大端.
int check_sys(int x)
{
return (*(char*)&x);
}
#include <stdio.h>
int main()
{
int a = 1;
if (check_sys(a))
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
三.浮点数的存储
1.浮点数的二进制转化
根据国际标准IEEE,任意一个二进制浮点数都可以表示为这样的形式(类似十进制的科学计数法)
(-1)^S * M * 2^E
其中S用来确定正负,正数为0,负数为1,M是具体的一个数,范围在1~2间,E代表指数位
比如5.5,用二进制表示101.1,然后类似科学计数法,101.1可以表示成1.011*2^2,然后是正数,所以5.5即可表示为(-1)^0 * 1.011 * 2 ^ 2,S为0,M为1.011,E为2
但是我们也可以发现一些像是无限不循环小数,比如pi,只能无限逼近,而不能精确表示出来,所以我们也说C语言中,不能直接进行浮点数比较,原因就在此,本身存储就不是精确的.
2.存储方式
无论是单精度(float)或者是双精度 (double),其在内存中都是按照这样的格式进行存储,唯一不同的是float是32个比特位,而double是64个比特位
bit位数目 | S | E | M |
float |
1 | 8 | 23 |
double | 1 | 11 | 52 |
对于M,由于M的取值范围必定在1~2之间,所以可以省略前面的1,例如1.011就可以省略1,只存入011进去,这样就可以多保存一位,达到24位
对于E,E是一个unsigned int类型的数字,但我们指数是可能出现负数的,所以为了让负数变为正数(无符号整型),像float类型,我们便加一个127(8个bit位能表示的最大负数)再存进去,对于double类型,则加一个1023再存进去.
Lg.例如0.5 二进制标准形式为(-1)^0 * 1.0 * 2 ^ (-1) (1) -1+127 = 126 (2)1.0的1可以去掉
其在内存中存储即为0 01111110 00000000000000000000000
当E全为0,它原本的指数即为-127(1000 0001 + 0111 1111),代表一个非常接近0的数字;
当E全为1,它原本的指数即为128(1000 0000 + 0111 1111), 并且有效数字也全为0,则代表无穷大,由S区分,正无穷还是负无穷.