char ———— 字符数据类型
short ——— 短整型
int ———— 整形
long ————— 长整型
long long ———— 更长的整形
float ———— 单精度浮点数
double ———— 双精度浮点数
数据类型的意义:
1、数据类型解决了“存”的问题:它决定了使用这个类型需要开辟空间的大小以及内存中的数据是如何存储的;
2、数据类型解决了“取(读)”的问题:它改变了看待内存空间的视角,比如在内存中同样的两块4个字节的空间,存放着同样的二进制码,如果这两块内存对应的两个变量类型不一样,那么它们的意义也就不一样了。
##字符在存储的时候存储的是ASCII码值,ASCII码值是整数,所以字符串类型属于整型
一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
那接下来我们谈谈数据在所开辟内存中到底是如何存储的?
比如:
我们知道为 a 分配四个字节的空间(整形在内存中的存储方式二进制序列)。
那如何存储?
下来了解原码、反码、补码 的概念
计算机中的整数有三种二进制表示方法,即原码、补码、反码。三者都包括符号位和数值位。
符号位:即用第一位表示符号,其余位表示值。符号位1表示负数、0表示正数。
正数的原码、补码、反码相同
负数的原码、反码、补码各不相同
1、原码:直接将整数转换成的二进制序列就是它的原码。
比如:以8位二进制为例
【1】原码:0000 0001
【-1】原码:1000 0001
原码是人脑最容易理解和计算的整数的二进制表示方式。
2、反码:负数的反码是在其原码的基础上,符号位不变,其余各个位取反。
【1】原码:0000 0001 【-1】原码:1000 0001
【1】反码:0000 0001 【-1】反码:1111 1110
3、补码:负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1。(也即在反码的基础上+1)
【1】原码:0000 0001 【-1】原码:1000 0001
【1】反码:0000 0001 【-1】反码:1111 1110
【1】补码:0000 0001 【-1】补码:1111 1111
对于负数,补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码再计算其数值。
4、机器在进行计算的时候是以补码的形式进行的计算。(对于整形来说:数据存放内存中其实存放的是补码)
原因:使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
5、为什么数据在内存中是倒着存放的呢?
这就要考虑到大小端的存储模式的问题了
什么大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中。
为什么有大端和小端:
为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元
都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short
型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32
位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因
此就导致了大端存储模式和小端存储模式。
例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为
高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高
地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则
为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式
还是小端模式。
兄弟们上题目
//输出什么?
#include
int main()
{
char a=128;
printf("%u\n",a);
rerurn 0;
}
分析:整数128的二进制放进char类型的a中是会发生高位截断,只放进去了低位数据。
整形【128】原码:0000 0000 0000 0000 0000 0000 1000 0000
char【128】原码:1000 0000————高位截断
char【128】反码:0111 1111
char【128】补码:1000 0000————反码+1
%u【128】补码:1111 1111 1111 1111 1111 1111 1000 0000——整型提升
以%u的要求打印,不讨论负数,因此原码、反码、补码相同
%u【128】原码:1111 1111 1111 1111 1111 1111 1000 0000——最终答案:4294967168
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。
举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。
那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,S=1,M=1.01,E=2。
IEEE 754规定:
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M
//输出什么?
#include
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);//————1
printf("*pFloat的值为:%f\n",*pFloat);————2
*pFloat = 9.0;
printf("num的值为:%d\n",n);————3
printf("*pFloat的值为:%f\n",*pFloat);————4
return 0;
}
分析:
1、略:以整数的形式打印 9
2、【9】补码:0000 0000 0000 0000 0000 0000 0000 1001
【9】IEEE标准:0 00000000 0000000001001
S=0 E=-126 M=0.0000000001001
【9】IEEE标准结果:(-1)^0 * 0.0000000001001 * 2^(-126)==0.0000
3、【9.0】浮点数在内存中的存储为 :1001.0
【9.0】IEEE标准:(-1)^0 * 1.001 * 2^3
【9.0】S=0 E=3 M=1.001
【9.0】二进制序列:01000001000100000000000000000000
【9.0】最终以%d打印表示为:1091567616
4、【9.0】以浮点数打印为:9.00000
整型和浮点型在内存中的存储方式截然不同,切不可混用
明天见兄弟们