大小端模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大小端模式相关的知识,希望对你有一定的参考价值。

参考技术A

加3g实验室的艰难之旅,遇到一道这样的实验室面试题:

** 输出结果为2000000 **
原题对a强制转换为int,64位机指针长度为八个字节,所以改为long int。

先来分析一下表达式,a为数组a[0]的地址,强制转换为长整型变为地址的数值后加一,实际为第一个元素的第二字节地址的数值。后转换为一指向整型的指针并赋值给ptr2。整型为4个字节,从第一元素第二字节开始往后读取四个字节,间接访问得出此四个字节代表的数值,并以十六进制输出。

那么问题来了,为什么是2000000,数组的整型元素在内存中是怎么储存的?这四个字节内存的是怎样的二进制数?为什么会这样储存?
经过度娘的帮助,它终于出现了—— 大小端模式

大端模式
大端模式是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中。大端模式与我们的阅读习惯相同。

小端模式
小端模式是指数据的高位保存在内存的高地址中,而数据的低位保存在内存的低地址中。

举例
int a=2;
地址:小----->大
在大端模式中,a存为:
0x00 0x00 0x00 0x02
在小端模式中,a存为:
0x02 0x00 0x00 0x00

在计算机系统中,地址是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了一个字节(8bit)的char之外,还有两个字节(16bit)的short型等超过一个字节的数据类型。另外,对于位数大于 8位的处理器,由于寄存器宽度大于一个字节。所以必然存在如何将多个字节安排的问题,因此就有了大端存储模式和小端存储模式。

小说《格列夫游记》中,小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。斯威夫特借以讽刺英国的政党之争,在计算机工业中指数据储存顺序的分歧。

一个简单的判断数据储存模式为大端模式还是小端模式。

a[5] = 1,2,3,4,5;

第一个元素和第二个元素储存方式
(地址:小--->大)
大端模式下:
0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x02
小端模式下:
0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00

截取第二个字节到第五个字节
大端模式:
0x00 0x00 0x01 0x00
小端模式:
0x00 0x00 0x00 0x02

读取数据
大端模式:
从高地址往低地址读取
0x00 0x00 0x01 0x00
读取数据转换为十六进制为100
小端模式:
从低地址往高地址读取
0x00 0x00 0x00 0x02
排成大端(0x02 0x00 0x00 0x00)
读取数据转换为十六进制为2000000

所以在大端模式下,结果为100。
在小端模式下,结果为2000000。

学C学得好迷啊,心好累,哈哈哈哈哈。

CPU大小端模式及转换

通信协议中的数据传输、数组的存储方式、数据的强制转换等这些都会牵涉到大小端问题。

CPU的大端和小端模式很多地方都会用到,但还是有许多朋友不知道,今天暂且普及一下。

一、为什么会有大小端模式之分呢?

因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。

但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的int型。另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。

对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。

二、什么是大端和小端?

大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。

小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

假如32位宽(uint32_t)的数据0x12345678,从地址0x08004000开始存放:
技术图片

再结合一张图进行理解:

技术图片

从上面表格、图可以看得出来,大小端的差异在于存放顺序不同。

三、数组在大端小端情况下的存储

以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value。

1.大端模式下
技术图片

2.小端模式下
技术图片

不知道大家对数组进行强制转换成整型数据没有?

如果你要进行强制转换,肯定要考虑大小端问题。

四、大小端谁更好?

小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。

大端模式:符号位的判定固定为第一个字节,容易判断正负。

总结:大端小端没有谁优谁劣,各自优势便是对方劣势。

五、大小端转换

开篇说了,实际应用中,大小端应用的地方很多通信协议、数据存储等。如果字节序不一致,就需要转换。
只要你理解其中原理(高低顺序),转换的方法很多,下面简单列列两个。

1.对于16位字数据

#define BigtoLittle16(A)   (( ((uint16)(A) & 0xff00) >> 8)    |                                        (( (uint16)(A) & 0x00ff) << 8))

2.对于32位字数据

#define BigtoLittle32(A)   ((( (uint32)(A) & 0xff000000) >> 24) |                                        (( (uint32)(A) & 0x00ff0000) >> 8)   |                                        (( (uint32)(A) & 0x0000ff00) << 8)   |                                        (( (uint32)(A) & 0x000000ff) << 24))

以上是关于大小端模式的主要内容,如果未能解决你的问题,请参考以下文章

CPU的大小端模式

C/C++ 关于大小端模式

大小端模式

大小端模式

C++怎么判断大小端模式

大小端模式