//数据类型的介绍以及所占据的空间
char //字符 1个字节
short //短整形 2个字节
int //整形 4个字节
long //长整形 4/8个字节 不同编译器不同
long long //更长的整形 8个字节
float //单精度浮点型
double //双精度浮点型
- 类型的基本归类:
- 整形:char/short/int/long(都包括unsigned和signed,平时编译器默认signed)
- 浮点型:float/double
- 构造类型:数组/结构体(struct/枚举(enum)/联合(union)
- 指针类型:int* pi/char* pc/float* pf/void* pv(因为没有具体值,只能用来暂时存放指针
//整形变量在内存中的存储
三种方法都有符号位和数值位,符号位用“0”表示正,用“1”表示负,数值为的表示方法不同
- 负数的原码、反码和补码
- 原码:二进制按照正负数的形式翻译
- 补码:原码按次取反
- 补码:反码+1
- 正数的原码、反码和补码:正数的三个码都相同
对于整形变量而言,数据内存中存放的是补码,用printf打印的是原码
- 原码和补码的转换
- 原码—>补码:原码按位取反+1
- 补码—>原码:补码-1取反/补码取反+1
//地址的存放方式
地址在内存中以字节为单位进行存放 ,每个地址单元对于1个字节,1个字节为8bit
这是初始化int a = 1的地址,a地址的16进制为0x00000001
注:
- 1个比特位为1个二进制位,在16进制的地值中换算可知:
1个16进制位 = 4个2进制位(2^4 = 16)
1个字节 = 1个比特位 = 1个二进制位
2个16进制位 = 8个2进制位 = 一个字节
- 1个数值超过1个字节,要存储到内存中,就有顺序的问题
所以这里可以理解为:01 为一个字节,后面的6个00两两为1个字节,正好4个字节对应整形
- 存储模式介绍:
- 大端:数据低位保存在内存高地址中,高位保存在低地址中
- 小端:数据低位保存在内存低地址中,高位保存在高地址中
对于0x00000001而言,01为处于低字节的位置(用百位数的个十百理解)
在VS中,地址存放应用了小端的存储方式
//数据存储和截断
<例1>
#include <stdio.h>
//输出什么
int main()
{
char a = -1;
signed char b =-1;
unsigned char c =-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
在一般的编译器中,char = signed char
当定义为整形数字时,访问时发生截断,此时会产生数据的整形提升:
最后得到a=b=-1
如若定义该数为无符号整形,那么在访问截断后发生升级时,无符号数高位补0:
此时c=256
<例2>
#include <stdio.h>
#输出什么
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
%u打印的是无符号整形,认为内存中存放的补码对应的是一个无符号数
%d是打印有符号整形,认为内存中存放的补码对应的是一个有符号数
对于字符类型打印数字,我们按照之前的流程进行
然后进行整形提升(char默认为有符号位,所以前面全部补上1)
此时因为要打印的是无符号整形,此时所有的1又都看成常数,所以结果得:
注:无符号类型的数字恒大于0
<例3>
#include <stdio.h>
//程序运行结果如何
int main()
{
unsigned int i;
for (i =9;i>=0;i--)
{
printf("%u\n",i);
}
return 0;
}
unsigned int 为无符号整形,恒大于0,最后0-1的时候得到的补码是全1,因为是无符号整形,会被看做一个很大的正数,不会等于0
<例4>
#include <stdio.h>
int main()
{
char a[1000];
int i;
for(i=0;i<1000;i++)
{
a[i]=-1-i;
}
printf("%d",strlen(a));
return 0;
}
- char的范围从-128~127,顺序为-1,-2,……-128,127……0,-1,-2……一直循环到1000次
- strlen求字符串长度,只找到\0(本质为0)之前的数字就停止,所以总共找到255个数字就停止
//浮点型在内存中的存储
根据国际标准IEEE754,任意一个二进制位可以表示成以下的形式:
- (-1)^S*M*2^E
- (-1)^S表示符号位,当S=0,V为正数;S为1,V为负数
- M表示有效数字,大于等于1,小于2
- 2^E表示指数位
- 例:5.5=101.1(101表示整数部分,.1为小数部分(2的-1次方))=1.011*2^2
- s=0;M=1.011;E=2
数据的存入:
<1>有效数字M:
- 前面说过,1<=M<2,也就是说,M可以写成1.xxxxx的形式。
- IEEE754中规定,在计算机内部保存时,默认这个数是第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。
- 比如保存1.01时,只保存01,等到读取的时候,再把第一位加上去
- 这样做的目的是为了节省一位有效数字。以32位浮点数为例子,留给M只有23位,将第一位1舍去后,等于可以保存24位有效数字。
<2>指数E:
- E本身为无符号整数,如果E为8位,它的取值范围位0-255;E为11位,取值范围在0-2047.
- 但科学计数法中的E是可以出现负数的,所以IEEE754规定:存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11的E,这个中间数是1023。
- 比如2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137
数据的取出:
<1>指数E:
- E不全为0或者不全为1:指数E的计算值-127或者1023,得到真实值,再将有效数字M前加上第一位的1
例如:0.5表示形式为:S:0 E:01111110(-1+127)M:0000000000000000000000
- E全为0:这时,浮点数的指数E等于1-127(1023)即为真实值,有效数字不再加上第一位的1,而是还原为0.xxxx的小数,这样是为了表示+-0,以及接近于0的很小的数字
- E全为1:这时,有效数字M全为0,表示+-无穷大
例子:
float类型只保留小数点后6位数字