数据类型介绍:
int //整型 占4个字节
short //短整型 占两个字节
long //长整型 占4个字节(vs2022中的数据)c语言标准中规定:
long long //更长的整型 占8个字节 sizeof(long)>=sizeof(int)
char //字符数据类型 占1个字节
float //单精度浮点数 占4个字节
double //双精度浮点数 占8个字节
数据类型的意义:
1.使用这个类型开辟内存空间大小(大小决定使用范围)
2.如何去看待空间的视角(同样是4个字节,里面储存的是浮点数还是整数)
整型家族有:
char char在储存的时候储存的是ASCll码值,ASCll码
unsigned char 是整数,所以归类的时候,字符属于整型家族。
signed char
short
unsigned short [int] short int num=0与short num=0 等价,int
signed short [int] 可以省略。short num=0与signed short num
int 等价。int和long类似。但char 是 signed char
unsigned int 还是unsigned char取决于编译器,常见的编译
signed int 器中char == signed char.
long
unsigned long
signed long
浮点数家族有:
float
double
构造类型(自定义类型):
数组类型 //数组类型为啥是自定义呢? 我们会根据需要改变数组的元素个数,这个时候方括号中的数值也随之改变,类型也就发生了改变。举个列子:int arr[10]的类型为int [10],而int arr[11]的类型则为int [11]
结构体类型 struct
枚举类型 enum
联合类型 union
空类型:
void表示空类型
通常用于函数的返回类型、函数的参数、指针类型。
void add() 表示该函数无返回值
{}
void add(void) 表示该函数不需要参数,不用给它传
{}
void *p 表示无类型指针
{}
对于整型来说,数据存放内存中其实存放的是补码
为什么储存补码呢?
使用补码,可以将符号位和数值域统一的处理,同时,加法和减法也可以统一处理(CPU只有加法器),此外,补码和原码的相互转换,其运算过程是相同的,不需要额外的硬件电路
正数 原码(直接按照该数值翻译成二进制形式就得到了原码)反码补码相同
负数 反码: 原码除符号位以外,其他位次按位取反得到反码
补码:反码+1
举个例子:
int a=-10
int b=20
//-10
//10000000000000000000000000001010 -原码
//11111111111111111111111111110101 -反码
//11111111 11111111 11111111 11110110 -补码
//0xff ff ff f6
//20
//00000000000000000000000000010100 -原码
//00000000000000000000000000010100 -反码
//00000000 00000000 00000000 00010100 -补码
//0x00 00 00 14
利用原反码进行计算的一个过程:
char a=-1
signed char b=-1
unsigned char c=-1
printf("a=%d b=%d c=%d",a,b,c);
答案是 ;你写对了吗?让我们分析一下它的一个过程;
//-1是整数
//10000000000000000000000000000001-原码
//11111111111111111111111111111110-反码
//11111111111111111111111111111111-补码
由于char a只有8个比特位,所以截取后八位存入
//11111111-a
//%d打印的是有符号的整数,但a不是,所以我们要提升(高位按符号位的数字来补够32位,无符号则以0补)成整数
//a有符号位,符号位为1,所以提升后为
//11111111111111111111111111111111-提升的补码
//10000000000000000000000000000001-还原得到的原码(输出的时候需要补码还原成原码进行输出)
最终输出a=-1,b也是同样的同样的,所以b=-1;
//11111111-c(c储存时的补码同a)
//00000000000000000000000011111111-提升
//00000000000000000000000011111111-原码(正数的原反码相同)
//最终c=255
负数的补码还原成原码可以有两种方式:
第一种是直接取反(符号位除外)+1;
第二种则是先减一,再取反;
大端小端储存是什么呢?
大端储存:
把一个数据高字节的内容放到低地址,把低字节内容放到高地址。
举个例子:
0x1234 低------------>高
12 34 00 00
小端储存:
把一个数据低字节的内容放到低地址,把高字节内容放到高地址。
同样举个例子:
0x1234 低------------>高
00 00 34 12
我可以设计一个简单的程序去检测是大端储存还是小端储存,参考代码如下下:
#include<stdio.h>
int main()
{
int a=1;
char *p=(char*)&a;
if(*p==1)
printf("小端");
else
printf("大端");
}
浮点数在内存中的储存方式是否于整型相同呢?
答案是否定的。
在国际标准IEEE754,任意一个二进制浮点数v都可以表示成以下面的形式:
1.(-1)^S*M*2^E
2.(-1)^S表示符号位,当S=1时,v为负数,当S=0时,v为正数。
3.M表示有效数字,大于1,小于2.
4.2^E表示指数位
以十进制5.0举个例子:
十进制5.0转换成二进制为101.0=1.01X2^2(可以类比十进制数15=1.5X10^1),那么以上浮点数v的形式S=0,M=1.01,E=2.
IEEE754规定:
E是一个无符号整数,对于8位的E范围0~255,对于11位的E范围0~2047,由于科学计数法中会出现负数,所以储存时真实值要加上一个中间数,对8位的E,这个中间数是127,对于11位的E,这个中间数位1023.
对于32位的浮点数,最高的一位是符号位S,接着的8位是指数E,剩下的23位是有效数字M。
对于62位的浮点数,最高的一位是符号位S,接着的11位是指数E,,剩下的52位是有效数字M。
对于E和M还有一些特殊的规定:
IEEE规定,计算机内部保存M时,默认第一位是总是1,因此可以省去,只保存小数点后面的数值。比如1.01,省略1只保存小数点后面的01
E取出的三种情况:
E不全为1也不全为0
这时,浮点数的指数E的计算值减去127,得到真实值,然后再将有效数字M前面加上第一位1.
E全为0
这时,浮点数的指数E=1-127(或1-1023)即为真实值.
有效数字M不再加上第一位1,而是还原成0.xxxxx的小数,这样做为了表示土0,以及接近于0很小的数。
E全为1
这时,有效数字M全为0,表示土无穷大(正负号取决于符号位S)