本文详细介绍了所有整形家族类型的取值范围;整形数据在内存中的存储方式(大小端存储方式)以及对应的解析,介绍讲解判断当前机器的存储方式代码练习题,掌握后编程基础更进一步牢固!!!
前面这篇博客写到了基本的内置类型->基本数据类型
这里主要补充各种整形类型取值范围
char↓
unsigned char
signed char
short ↓
unsigned short [int]
signed short [int]
int↓
unsigned int
signed int
long↓
unsigned long [int]
signed long [int]
这里unsigned表示无符号 signed表示有符号
整形数据在内存中是以二进制补码形式存储,我们一般正常看到的是二进制原码转换成的十进制数
对于进制数转化和有符号无符号位的数据原反补如何转换可以看这篇博客->进制数和原反补转换
char类型是字符型类型,但是实际上也是整形,因为它是以Ascll码字符形式表示的,实际对应的还是ASCLL码值,是整形, 类型长度为1字节
char分为unsigned char 和 signed char
unsigned char 取值范围
unsigned char表示无符号的字符类型 类型大小1字节 八位二进制位组成
最大值为11111111最高位不是符号位 此时表示是1 转化为十进制数为255
最小值为00000000 转化为十进制数为0
取值范围为0~255
signed char 取值范围
signed char 表示有符号的字符类型 一般signed可以省略 类型大小1字节 最高位表示符号位 1表示负数 0表示正数
最大值为01111111 转化为十进制为2的7次方减1为127
最小值为10000000 因为00000000表示0而10000000表示-0但没有这个说法,此时已经有数表示0了而此时这个数则不能再为0,且-127到127上都有数了此时这串数字遵循半计算办规定的说法将它转化为数字-128
也可以根据整形提升转化为整形补24个1为11111111111111111111111110000000 转化为原码为10000000000000000000000010000000 转化为整形为-128
取值范围为-128~127
short类型是短整型,分为unsigned short和signed short是整形类型,类型长度2个字节
unsigned short取值范围
unsigned short表示无符号短整型 没有符号位,大小为2字节即16位
最大值为11111111111111 转化为原码十进制数为2的16次方减1为65536
最小值为0000000000000000转化为十进制数为0
取值范围为0~65536
signed short取值范围
signed short 为有符号的短整型 signed可以省略 大小为2字节
最大值为01111111111111 为2的15次方-1 为32767
最小值为1000000000000000 跟有符号的char一样半计算半规定最小值为-32768
取值范围为(-2)^15 到2^15-1(-32768~32767)
int类型为整形 类型长度4字节 分为unsigned int和signed int
unsigned int取值范围
0~2^32-1 (0~4,294,967,295)
signed int取值范围
(-2)^31~ 2^31-1(-2,147,483,648~2,147,483,647)
long类型表示长整形 但是它类型长度和int一样是4字节 也分有符号和无符号长整形和有符号无符号的整形取值范围也对应一样
longlong类型为更长的整形类型,类型长度为8字节是最大的整形类型分有符号和无符号
unsigned longlong取值范围
取值范围为0~2^64-1 (0~18,446,744,073,709,551,615)
signed longlong取值范围
取值范围为(-2)^63 ~ 2^63-1 (-9,223,372,036,854,775,808~9,223,372,036,854,775,807)
我们之前讲过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的
而一个整形空间由四个内存单元组成,它在内存中的存储方式也是不同的
而存储方式分为有大端存储和小端存储
为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元
都对应着一个字节,一个字节为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处理器还可以由硬件来选择是大端模式
还是小端模式。
在内存中除了字符类型以外的其他类型 都会占用2个即以上的内存单元
用整形举例:假设一个整形变量a 里面存放整数1,在内存中以二进制原码形式存在则为
00000000000000000000000000000001 八个位表示一个字节
整形空间有四个内存单元 而每个内存单元都存放着对应这个整形的一个字节
为了方便展示将这32个二进制转化为16进制形式0x00 00 00 01
此时两个十六进制为一组表示一个字节,
分布存放在这四个内存单元里 ,
但是按什么样的规则顺序存储字节呢?这是没有规定的,每个人都有不同想法,因此在这多种不同的存储方式中留下最后两种存储方式被称为大端存储 小端存储.
这两种存储方式是根据不同编译器不同设计者设计的,一种编译器只会有一种存储方式
但是最后得到的结果是不会改变的!!!
现在有一群人,每个人都得到一个鸡蛋,现在要每个人敲开鸡蛋吃,
最后结果肯定是每个人都把鸡蛋吃完了
但是,每个人敲开鸡蛋的方式,你能保证一致吗?
有些人选择从尖的部位敲开,有的人选择从扁一点的部分敲开鸡蛋
这都是没有特殊规定,是根据每个人自己的习惯都是可以的
最后的目的只是为了吃掉鸡蛋
和吃鸡蛋一样大小端存储方式,不同内存单元存放的数据的字节位方式不同,但是取出来时会按自己的方式取出,最后得到的结果是不变的!
大端存储方式是将数据低位上的内容放在高地址的内存单元内,数据高位的内容放在低地址的内存单元内
根据上面分析 a里面的整数1被划分为0x 00 00 00 01
而如何区分高位低位呢
123这串数字 3是个位 1是百位,此时3肯定是低位上,而1则是高位,0x 00 00 00 01一样,按字节将其化为四组 01则属于低位上的内容 依次往左 位权重更高
而一个整形内存空间 分为四个内存单元,假设从左到右排列,左边的内存单元位与的位置是低地址,最右边的则是高地址,
01是数据低位上的内容 放在高地址上的内存单元依次按规则存放为00 00 00 01 也就是顺序存储即为大端存储
根据大端存储方式,这四个内存单元如何存放这四个字节内容呢?
按以字节为单位将数据顺序存储在每个内存单元里,即数据低位上的内容放在高地址处的内存单元数据高位的内容放在低地址处的内存单元内
小端存储方式是将数据低位上的内容放在低地址处的内存单元里,数据高位的内容放在高地址处的内存单元里
还是这张图, 整数1在内存中以补码十六进制表示为0x00 00 00 01
假设a整形变量的四个内存单元从左往右排列,最左边的是低地址,最右边的是高地址
此时将01为数据低位的内容这个十六进制表示的一个字节放在最左边的内存单元里,依次按规则往后方此时内存里为01 00 00 00 也就是倒序存储,即为小端存储.
按小端存储又是怎样存放的?
根据小端存储规律将数据低位上的字节放在低地址处的内存单元里,高位上的字节内容放在高地址处的内存单元里,此时就是小端存储
不要认为存储方式不重要,即是练内功,也是一道经典面试题
下面这串代码,即巧妙的判断了当前机器的是大端存储还是小端存储.
#include
int main()
{
int a = 1;
char* pa = (char*) & a;
if (*pa == 1)
printf("小端");
if (*pa == 0)
{
printf("大端");
}
return 0;
}
代码设计创建一个整形变量a 此时在内存里申请了四个字节的内存空间,即四个连续的内存单元,
然后将1这个整数即内存中以二进制补码形式00000000 00000000 00000000 00000001 存在
为方便识别将其转换为十六进制为0x00 00 00 01 假设当前是小端存储,则是将数据低位上的字节内容放在低地址处的内存单元 高位内容放在高地址处内存单元,而假设左边为低地址右边为高地址
此时存放为00 00 00 01 ,即变量a开辟的整形空间存放这个整数的形式,
如果是大端存储则是01 00 00 00
此时&a得到a变量的地址,
在前面博客讲到&a得到的是这个整形变量起始地址,因为整形变量有四个内存单元,得到的是地址最低的那个内存单元的地址,
此时将其强制类型转换为char*,表示看待这个指针以字符指针类型看待,将其存在字符指针变量pa里
此时pa存放的就是a的起始内存单元地址也表示的是一个字符类型的地址
此时通过解引用访问的是这个地址指向的位置上的内存单元,因为这个指针是字符型访问的就是这个内存单元的内容,而如果内存单元是01,取出来的则是00000001这个二进制序列,
通过整形提升为00000000000000000000000000000001最后得到的是1,此时表示的是低地址上的内存单元里存放的是01对应存储方式就是小端存储,
如果是00 通过整形提升为00000000000000000000000000000000 最后为数字0,表示的这个低地址上的内存单元里存放的是00对应的存储方式就是大端存储
通过只访问这个整形内存空间里四个内存单元低地址处的那个内存单元里的值间接得到整个机器的存储方式.
如果不会调试的可以看我这篇博客->调试技巧
通过一步步调试,查看当前的内存情况,此时在地址栏处输入&a得到当前地址作为起始地址后所有的内存单元内的信息越往后的内存单元地址越高, 可以看到01 00 00 00 就是对应的a这四个内存单元里的值,开头的是01表示低地址上的内存单元的内容
也表示出了01是数据低地址位上的内容放在了低地址处
可以看出当前机器的存储方式是小端存储!!!
不管编译器是什么存储方式,最后得到的数据都是会按原来存放时的规律再次取出后组成数据原来的样子,所有大端小端存储方式并不会改变数据原来的值,只是表示不同的存储方式.
看到这里,基本已经了解了大端小端这两种数据存储方式,而这种数据存储方式只限于整形,浮点型的存储是不一样的,在下一篇博客里会详细讲到. 修成内功,打好基础,为后面学习c语言学习更多编程知识会事半功倍!!!
写文不易,一键三连支持下吧~~~