内存的大小端排序归并排序 是什么意思思

用C语言程序判断大小端模式
字体:[ ] 类型:转载 时间:
本文介绍了用C语言程序判断大小端的方法,与大家分享一下。
1.大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端模式相反
&2.为什么有大小端之分???
&因为在计算机系统中,存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节=8bit。在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,如何安排多个字节的存储,这就有了大端存储模式和小端存储模式
3.各自的优势:
小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式:符号位的判定固定为第一个字节,容易判断正负。
4.常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式.
5.C语言判断大小端模式
代码如下:void IsBigEndian(){&short int a = 0x1122;//十六进制,一个数值占4位&char b =& *(char *)&a;& //通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)&if( b == 0x11)//低字节存的是数据的高字节数据&{&&//是大端模式&}&else&{&&//是小端模式&}}
代码如下:void IsBigEndian()//原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间{&union temp&{&&&&&}&temp.a = 0x1234;&if( temp.b == 0x12 )//低字节存的是数据的高字节数据&{&&//是大端模式&}&else&{&&//是小端模式&}}
在我的机子上验证了一下是小端模式
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具1610人阅读
C/C++(89)
内存大小端判断
思路:联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了
&&CPU对内存是采用Little-endian还是Big-endian模式读写。
给出c代码,linux其实也差不了多少
#include&iostream&
using&namespace&
union&Judge&&&
&&short&s;
&&char&ch[sizeof(short)];
int&main()
&&flag.s&=&0x0102;
&&if&(&sizeof(short)&!=2&)
&&cout&&&&测得short类型有&&&sizeof(short)&&&个字节&&&
&&if&(&flag.ch[0]&==&2&&&&flag.ch[1]&==&1&)&&&
&&cout&&&你用的电脑处理器是小端模式!&&&
&&else&if&(&flag.ch[0]&==&1&&&&flag.ch[1]&==&2&)
&&cout&&&你用的电脑处理器是大端模式!&&&
&&cout&&&未知模式&&&
&&system(&pause&);
&&return&0;
===========================================================
大端与数字顺序一致
0x100&0x101&0x102&0x103
&12&&&34&&&&&56&&&&78
0x100&0x101&0x102&0x103
&78&&&&56&&&&34&&&&12
大端一致(即数字顺序一致)
一、什么是大小端问题
(From《Computer&Systems,A&Programer's&Perspective》)在几乎所有的机器上,多字节对象被存储为连续的字节序列,对象的地址为所使用字节序列中最低字节地址。
&&&&&&&&小端:某些机器选择在存储器中按照从最低有效字节到最高有效字节的顺序存储对象,这种最低有效字节在最前面的表示方式被称为小端法(little&endian)&。这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
&&&&&&&大端:某些机器则按照从最高有效字节到最低有效字节的顺序储存,这种最高有效字节在最前面的方式被称为大端法(big&endian)&。这种存储模式将地址的高低和数据位权(即个十百千万...)有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
二、为什么会有大小端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为&8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于&8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。
例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。
对于&大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。
小端模式,则刚好相反。
=============================================
端模式分为:大端字节序和小端字节序,也就是字节在内存中的顺序。
内存中存放数据的顺序是:由低到高。
大端字节序:高字节存于内存低地址,低字节存于内存高地址。如一个long型数据0x
内存低地址--&&0x12
    .  0x34
    .  0x56
内存高地址--&&0x78
小端字节序:低字节存于内存低地址,高字节存于内存高地址。
内存低地址--&&0x78&&&&&&&&&&&
&&&&&&&&&&&&&&&.&&&&  0x56
&&&&&&&&&&&&&&&.&&&&  0x34
内存高地址--&&0x12
&&&&&&&&&&&&&&字节的大端序还是小端序是由CPU决定的。
我们常用的X86结构是小端模&式,而KEIL&C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
网络字节序:就是大端字节序。规定不同系统间通信一律采用网络字节序。
在VC中的实验如下:
int&&temp&=&0x;
  调试中,该变量在内存中的表现形式是78&56&34&12,但其真实的数值还是0x,只不过
内存中表现的字节顺序与我们所认为的字节顺序刚好是反着的,同时也说明我的PC是遵循大端字节序的。
=========================================================
需要考虑大小端(字节顺序)的情况?
1、所写的程序需要向不同的硬件平台迁移,说不定哪一个平台是大端还是小端,为了保证可移植性,一定提前考虑好。
2.&在不同类型的机器之间通过网络传送二进制数据时。&一个常见的问题是当小端法机器产生的数据被发送到大端法机器或者反之时,接受程序会发现,字(word)里的字节(byte)成了反序的。为了避免这类问&题,网络应用程序的代码编写必须遵守已建立的关于字节顺序的规则,以确保发送方机器将它的内部表示转换成网络标准,而接受方机器则将网络标准转换为它的内部标准。
3.&当阅读表示整数的字节序列时。这通常发生在检查机器级程序时,e.g.:反汇编得到的一条指令:
80483bd:&01&05&64&94&04&08&&&&&&&&add&?x,&0x8049464
3.&当编写强转的类型系统的程序时。
例1:如写入的数据为u32型,但是读取的时候却是char型的:
如:0x1234,&大端读取为12时,小端独到的是34。
例2:将buffer中的数转换为整型:
如:int&src&=&0x1234
&&&&&&&memcpy(buffer,&src,&sizeof(int));
&&&&&&大端:buffer[4]&=&{0x01,&0x02,&0x03,&0x04};
&&&&&&小端:buffer[4]&=&{0x04,&0x03,&0x02,&0x01};
提高程序的可移植性
使用宏编译
#ifdef&LITTLE_ENDIAN
//小端的代码
//大端的代码
大、小端之间的转换代码
1、小端转换为大端
#include&&stdio.h&
void&show_byte(char&*addr,&int&len)
&&&&&&&int&i;
&&&&&&&for&(i&=&0;&i&&&&i++)
&&&&&&&&&&&&&&printf(&%.2x&\t&,&addr[i]);
&&&&&&&printf(&\n&);
int&endian_convert(int&t)
&&&&&&&int&
&&&&&&&int&i;
&&&&&&&result&=&0;
&&&&&&&for&(i&=&0;&i&&&sizeof(t);&i++)
&&&&&&&&&&&&&&result&&&=&8;
&&&&&&&&&&&&&&result&|=&(t&&&0xFF);
&&&&&&&&&&&&&&t&&&=&8;
&&&&&&&return&
int&main(void)
&&&&&&&int&i;
&&&&&&&int&
&&&&&&&i&=&0x1234567;
&&&&&&&show_byte((char&*)&i,&sizeof(int));
&&&&&&&ret&=&endian_convert(i);
&&&&&&&show_byte((char&*)&ret,&sizeof(int));
&&&&&&&return&0;
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:664515次
积分:7865
积分:7865
排名:第1888名
原创:123篇
转载:339篇
评论:57条
(2)(1)(1)(1)(7)(10)(8)(7)(11)(11)(11)(8)(10)(11)(16)(24)(15)(12)(13)(10)(7)(7)(3)(11)(22)(50)(1)(2)(5)(7)(6)(20)(51)(9)(9)(37)(11)(4)(2)(9)2016年4月 VC/MFC大版内专家分月排行榜第二2014年11月 VC/MFC大版内专家分月排行榜第二2014年1月 VC/MFC大版内专家分月排行榜第二2013年10月 VC/MFC大版内专家分月排行榜第二2013年9月 VC/MFC大版内专家分月排行榜第二2013年6月 VC/MFC大版内专家分月排行榜第二2013年4月 VC/MFC大版内专家分月排行榜第二2012年6月 VC/MFC大版内专家分月排行榜第二
2016年10月 VC/MFC大版内专家分月排行榜第三2016年2月 VC/MFC大版内专家分月排行榜第三2015年10月 VC/MFC大版内专家分月排行榜第三2015年7月 VC/MFC大版内专家分月排行榜第三2012年10月 VC/MFC大版内专家分月排行榜第三
2014年11月 VC/MFC大版内专家分月排行榜第三
2016年8月 VC/MFC大版内专家分月排行榜第二2016年7月 VC/MFC大版内专家分月排行榜第二2016年6月 VC/MFC大版内专家分月排行榜第二2015年6月 VC/MFC大版内专家分月排行榜第二
2016年9月 VC/MFC大版内专家分月排行榜第三2016年4月 VC/MFC大版内专家分月排行榜第三2015年4月 VC/MFC大版内专家分月排行榜第三2012年8月 VC/MFC大版内专家分月排行榜第三
2016年8月优秀大版主
2016年9月 总版技术专家分月排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
2008年2月 VB大版内专家分月排行榜第一2003年4月 VC/MFC大版内专家分月排行榜第一2002年11月 VC/MFC大版内专家分月排行榜第一
2011年11月 VC/MFC大版内专家分月排行榜第二2008年3月 VB大版内专家分月排行榜第二2008年3月 硬件/嵌入开发大版内专家分月排行榜第二2003年4月 其他开发语言大版内专家分月排行榜第二2003年4月 VB大版内专家分月排行榜第二2003年3月 VB大版内专家分月排行榜第二
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。大小端字节序问题
想起以前在汇编语言和数字逻辑的时候也有接触到一些这个概念,已经有点模糊了,搞不清楚哪个是低位在前哪个是高位在前。后来在Wiki和Google的帮助下也算摸清楚了一些Endianness的概念。
一、字节序的起源
在计算机中,字节序()是数据中单独的可取地址的亚型(words,bytes和bits)在外部存储器中存储的顺序。通常在提到四字(ddword)、双字(dword)和字(word)的时候需要考虑其实际的字节顺序,为了简便起见它的英文也常常表示为Byte
Endianness这个词源自1726年Jonathan Swift的名著:Gulliver’s
Travels(格列佛游记),在书中有一个故事,大意是指Lilliput(小人国)的领导下了一道指令,规定其人民在剥水煮蛋时必须从little-end(小的那一端)开始。这个规定惹恼了一群觉得应该要从big-end(大的那一刻)开始剥的人。事情发展到后来,竟然演变成一场纷战。支持小的那端的人被称为little-endian,反之则被称为big-endian(在英语中后缀“-ian”表示“xx人”的意思)。1980年Danny
Cohen在他的论文“On Holy Wars and a Plea for
Peace”中第一次使用了Big-和Little-这两个术语,最终它们成为了计算机通过网络与其他计算机连接时所要考虑的极其重要的一个问题。
二、字节序的种类和其表示
那么为什么要引入字节序呢。我们都知道,计算机存储中最小的单位是位(bit),而8bit构成一个字节(byte)。在一个32位的CPU中,字长为32bit,也就是4byte,数据要想存放在内存中供CPU读取和写入,就需要拥有一定的存放顺序。这样不同的CPU可接受的字节序有可能不同,那么在设计硬件和软件时数据的存放问题也需要分开考虑。
数据都有所谓的“有效位(Significant
Bit)”,顾名思义它表示了“数据存放有效的位置”,而字节序的分类就是依赖于有效位来进行划分的。在一个字节当中,数据的有效位的顺序已经得到了大多数硬件生产商的共识,那就是最高有效位优先(Most
Significant Bit
First),例如我们用8位二进制数来表示十进制数123为,其第一位的0就是最高有效位,而最后一位的1就是最低有效位,在一个字节当中,几乎当前所有的硬件都采用了这种直观的字节序。
然而情况在离开了单字节时就有所不同了。不同的硬件产商对于数据占据多个字节时拥有怎样的字节序有着不同的理解,具体说来分为以下三类:
Big-Endian(大字节序):最高有效字节优先,更高的字节有效位占据着更低地址的内存空间,其在内存中的表示与直观吻合,
Little-Endian(小字节序):最低有效字节优先,更低的字节有效位占据着更低地址的内存空间,其在内存中的表示与直观相反,以及
Mixed-Endian(混合字节序)或者Middle-Endian(中字节序):在16位字(word)中的字节序与32位字(dword)中的字节序不相同。这种类型的字节序较为少见。
一些知名的使用Little-Endian的处理器体系结构包括了:x86、6502、Z80、VAX以及PDP-11,使用Big-Endian的处理器通常是Motorola的处理器,例如:、PowerPC(即Macintosh在迁移到x86之前所采用的处理器)以及System/370。这也是为什么在文章开头提到的文档中使用Big
Endian / Motorola standard这样的词汇的原因。
更进一步的,像ARM、PowerPC、Alpha、SPARC
V9、MIPS、PA-RISC和IA64等体系结构可以支持可切换的字节序这样的特性,这个特性可以提高效率或者简化网络设备和软件的逻辑。这种可切换的字节序被称为Bi-Endian,用于硬件上意指计算机或者传递数据时可以使用两种不同字节序中任意一种的能力。
文字不够直观,下面以数值0x0A0B0C0Dh为例说明Big-Endian和Little-Endian在内存布局上的不同:
Big-Endian在内存中的表示
increasing
addresses& →
在这个例子中,最高有效字节(MSB)为0Ah,储存在最低地址的内存中;次高有效位为0Bh,储存在接下来的内存中,依此类推。这种字节序与从左向右的顺序读取十六进制数值非常类似。
以16位元素大小查看:
increasing
addresses& →
最高有效元素现在保存的是0A0Bh,接下来的元素保存0C0Dh.
Little-Endian在内存中的表示
increasing
addresses& →
在这个例子中,最低有效字节(LSB)的值为0Dh,储存在最低地址的内存,其他字节依照字节有效性的递增依次存放。
用16位元素大小表示
increasing
addresses& →
最低有效16位单元储存的是值0C0Dh,紧接着储存值0A0Bh。
三、字节序的重要性及其应用
如前所述,不同硬件的体系结构接受不同字节序的数据表示,因此当同一个文件在不同的机器中进行读取和写入的时候,其所支持的字节序就显得尤为关键。设想在x86计算机中将(123888)10写入二进制文件中,由于x86支持Little-Endian,所以该数在文件中保存为(0000003F1E)16。当在PowerPC计算机中读取该整数时,由于它支持的是Big-Endian,故读取的结果将是(16158)10,大相径庭。
同样的情况也会出现在网络传输当中,当你从支持一种字节序的机器发送数据到支持相反字节序的机器时,将会得到非预期的结果。这种错误在网络传输当中尤为突出,因为你无法决定发送你所需文件机器所支持的字节序,因为这些机器可能分散在世界各地,不是人为所能控制的。
为了更明确的说明上述问题,考虑下列代码:
1: Example
01&#include
02&#include
&string.h&
04&int&main&(int&argc,&char*&argv[])&{
05&&&&&FILE*&fp;
08&&&&&struct&{
09&&&&&&&&&char&one[4];
10&&&&&&&&&int&&two;
11&&&&&&&&&char&three[4];
12&&&&&}&data;
15&&&&&strcpy&(data.one,&“foo”);
16&&&&&data.two&=&0&;
17&&&&&strcpy&(data.three,&“bar”);
20&&&&&fp&=&fopen&(“output”,&“wb”);
21&&&&&if&(fp)&{
22&&&&&&&&&fwrite&(&data,&sizeof&(data),&1,&fp);
23&&&&&&&&&fclose&(fp);
这是一段很简单的C语言代码,作用就是向一个data结构体赋值并且将它写入文件当中,从结果Listing 2和Listing
3当中我们就可以看到支持不同字节序的机器在处理数据时候存在的不同。
Listing 2. hexdump &C
output on big-endian machines
6f 6f 00 01 23 45 67
62 61 72 00
|foo..#Egbar.|
Listing 3.
hexdump -C output on little-endian machines
6f 6f 00 67 45 23 01
62 61 72 00
|foo.gE#.bar.|
注意力好的同学一眼就能发现,在写整数的时候,数据保存的顺序依赖于不同的机器,而字符串却不受此影响,这是为什么呢?这就牵涉到字节序是如何如代码进行影响的了。
字节序并不会影响数据存储的所有方面,例如对一个整数进行bitwise或者bitshift的操作,你是不需要去注意对应的字节序的。因为多字节的顺序是由计算机来维护的,对于程序员来说,一个整数的最低有效位仍然是最低有效位,最高有效位亦然,并不会由于它在计算机底层存储模式的改变而影响到有效位的含义。
同样的,字节序不会影响到C风格字符串在计算机底层的存储顺序,这是为什么呢?考虑到一个C风格字符串的实质是一个包含着许多char的数组,每一个char在现代计算机中几乎都是表示计算机中的一个字节。因此,当读写C风格字符串时,其最小的元素单位是一个字节;而且数组在内存单元中地址的排列顺序是递增的,例如定义char
str[5];这么一条语句,假设&str[0]的地址为1000,则&str[1]的地址为1001,依次类推。所以不论从直观含义或者底层技术来看,字符串的存储都是相对字节序独立的,这个特性将应用在接下来的许多小技巧中。
那么字节序除了影响到多字节数据在内存中的存放顺序以外,在写代码的时候还有什么需要注意的呢?当对一个数据进行类型转换的时候,需要记住特定的字节序很可能影响到类型转换的结果。假设我们有Listing
4所列的这么一段代码
4: 强制类型转换
1&unsigned&char&endian[2]&=&{1,&0};2&short&x;3
4&x&=&*(short&*)&endian;
那么最后得到x的结果是多少呢?是不是简单的就是endian数组的第一个元素1呢?答案是错,x的数值需要根据运行时的环境来决定。让我们回忆一下C语言的指针指向多大的内存以及怎么去解释所指的这块内存是由指针所指向的类型来确定的,在上述代码中,将endian数组的首元素指针强制转换成short
*的指针,那么编译器在解释它的时候将不再把它指向的内存空间视为1 byte,而是short的长度——2
byte;更重要的是当我们对这个指针解引用的时候将会得到的值会是什么。再回到上面所提到的字符串或者字符数组在计算机中就是依照数组顺序存放的,那么这个时候endian数组占用了两个字节,其内存数据为:0100。当该指针强制转换为指向short的指针并解引用时,计算机将一次读取两个字节,这个时候字节序就发挥它的影响了。在支持Little-Endian的机器中x的值将是1(读取为0001),而在支持Big-Endian的机器中x的值就是256(读取为0100)。因此在对指针进行类型转换并解引用,特别是在单字节到多字节数据的转换时,要特别注意字节序是否会使得预期结果出现偏差。
单字节指针到多字节指针的转换其实并不完全像Listing
4所举例子那样恼人,它还有其他的用途,例如我们可以使用这个特性在运行时判断当前计算机所支持的字节序,这样可以使得程序员在编写代码的时候更加灵活,也使得代码更加强健(robust)。基本的思路就是先定义一个int变量1,这个变量在不同的计算机中将有两种不同的存储顺序:(Little)以及(Big),然后我们将指向这个变量的指针强制转换为指向字符的指针,再解引用根据它的值是0还是1就可以得出当前机器支持的字节序的,代码很简单:
5: 判断字节序
1&int&i&=&1;23&if&(*(char*)&i&==&0)
Big Endian
Little Endian
利用char*的这种特性还可以方便的反转数据顺序以适应不同的机器,怎么编写这样的代码不如让你来思考一下?
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。2684人阅读
[ C/C++](5)
&&C语言深度剖析&&学习中....
最近在学习C语言深度剖析,读到了关于数据在内存中的存放:大端、小端模式...
关于 big-endian &and &little-endian ...
自编Test小程序:
#include &stdio.h&
#include &stdlib.h&
int main(void)
& & & & int a[5] = {0x3,0x5}; & & & &
& & & & int *p1 = (int *)((int)a);
& & & & int *p2 = (int *)((int)a+1);
& & & & int *p3 = (int *)((int)a+2);
& & & & int *p4 = (int *)((int)a+3);
& & & & printf(&%8x %8x %8x %8x\n&,a,(a+1),(a+2),(a+3));
& & & & printf(&%8x %8x %8x %8x\n&,*a,*(a+1),*(a+2),*(a+3));
& & & & printf(&%8x %8x %8x %8x\n&,p1,p2,p3,p4);
& & & & printf(&%8x %8x %8x %8x\n&,*p1,*p2,*p3,*p4);
& & & & system(&pause&);
& & & & return 0;
运行结果: &(Dev- C++编译)
查看内存和数据:
1、X86系统中,一个字节占8位(废话)。
2、小端模式中,低位数据存储于低地址中,高位数据存储在高地址中。
3、0x12ff6c地址内存储的数据是:0x &, &0x12ff70地址内存储的数据是:0x
4、0x23存储于高地址(0x12ff73)中 &,0x89存储于高地址(0x12ff70)中。
5、 &取出&0x12ff6c 中的数据,则为:0x 00 00 11 11
& & & & 取出&0x12ff6d &中的数据,则为:0x 89 00 00 11 &
取出 0x12ff6e 中的数据, 则为:0x 67 89 00 00 &
取出 0x12ff6f 中的数据, 则为:0x 45 67 89 00 &
取出 0x12ff70 中的数据, 则为:0x 23
int 型数据占据4个字节,每4字节为一个数据块,读数据是存数据的逆方向,
即高地址的数据放在高位, 低地址的数据放在低位。
知识扩展:
(from:的博客)
字节大小端
& & & & 大端字节序对应的英文单词是big-endian,小端字节序对应的英文单词是little-endian。
& & & & endian这个单词在英文词典里一般查不到,这个单词出自Jonathan Swift写的讽刺小说《格列佛游记》,这本书中描述了一个小人国里总会发生一些意想不到的事情,有一次小人们因为是应该先从鸡蛋大的一端敲开还是小的一端敲开而引发了战争,支持从大端敲开的人被归为Big
Endian,支持从小端敲开的人被归为Littile Endian。
& & & & 在计算机世界里同样存在着这种“战争”,各个芯片厂商为了自身利益的需要提出了不同的两种字节序,从而引发了应该使用哪种字节序的争论。为了平息这场争论,Danny Cohen在其著名的论文&On Holy Wars and a
Plea for Peace&中引入了big-endian和little-endian,分别对应着这两种字节序。这两种字节序共存的现实给软硬件设计带来了不小的麻烦,这种非常形象贴切的描述对这种情况真是一个不小的讽刺。
绝大部分处理器的最小存储单元是Byte,也就是说每个地址对应一个字节的数据,8位机时代对于处理器来说是不存在大小端问题的,它的机器指令只能以Byte为单位对存储数据进行访问,对多Bytes长度的数据类型进行访问也是由相对应多个的机器指令组成的,每条机器指令中规中矩的访问一个Byte的数据。但到16位机、32位机甚至64位机时代问题就来了,为了保持兼容性,这些处理器仍然是以Byte作为最小的存储单元,每个地址仍对应一个Byte数据,但为了提高性能,处理器增加了同时访问多字节的机器指令,以32位机为例,它的一条机器指令可以同时访问32bits的数据,也就是4地址的数据,对应4个字节。4个字节的数据作为一个整体表示一个数,那么它们在内存中是如何存放呢,这就涉及到大小端模式的问题了,看下图:
图 24&&数值在内存中的存放模式
& & & & 大端模式是将数的高位字节放在低位地址,将数的低位字节放在高位地址,而小端模式则正好反过来,是将数的高位字节放在高位地址,将数的低位字节放在低位地址,如上图所示。
我们再来看看上节例2.4.7中值为0x的int型变量addr在Memory窗口的截图,如下图所示:
图 25&&查看Memory内存窗口
& & & & 其中最高位字节0x12被放在了最高地址0x2000020B,次高位字节0x34被放在了地址0x2000020A,次低位字节0x56被放在了地址0x,最低位字节0x78被放在了地址0x,按照这个存放顺序来看,我们所使用的处理器是小端模式的。
& & & & 如果我们只使用变量而不直接访问内存是不会觉察到大小端模式存在的,比如说我们定义了一个int型的变量addr,在使用addr这个变量时它所占用的4字节内存空间是作为一个整体出现的,我们所能看到的只有变量addr,看不到它内部的4个字节,变量addr像一个黑盒一样罩住了它内部的4个字节的内存空间,我们访问addr时,处理器会按照大端或者小端的规则将这4个字节内存空间中的数据与变量addr的数值对应起来。对内存的访问分为读和写两种操作,下面我们仍以0xx2000020B地址的变量addr为例来看看大小端模式的工作流程。
& & & & 大端模式
将数0x写入到变量addr中时,硬件就会将数0x看作成4个字节0x12、0x34、0x56和0x78,分别存入0xx2000020B这4个地址中,每个字节的数与地址按照大端模式的规则一一对应,这种对应关系是由硬件自动完成的。
图 26&&大端模式
& & & & 当读取变量addr数值时,硬件就会从0xx2000020B这4个地址中读出4个字节,按照大端模式的对应规则将这4个地址中的4个字节恢复成0x,这种对应规则也是由硬件自动完成的。
& & & & 小端模式
& & & & 从软件角度来看,小端模式的读写过程与大端模式的读写过程是一样的,写过程是将数0x写入到变量addr中,读过程是从addr中取得数0x,与大端模式不同之处在于硬件部分,硬件在执行读写时采用了数与地址不同的映射关系,这才是产生大小端模式的根本原因。
图 27&&小端模式
& & & & 硬件通过映射关系屏蔽了变量addr所对应的内存空间细节,因此软件访问变量addr根本就感觉不到大小端的存在,这就好比是我们把钱存到银行,我们不知道银行把这些钱放在哪里了,我们只需要知道我们还能从银行取出这些钱就行了。如果我们进入银行跟踪这些钱,也许会发现这些钱根本就没在银行里,可能已经被其他人取走了,在我们取钱时银行又拿了别人的钱给了我。进入银行就好比我们绕过了硬件的映射关系,直接去查看内存,大小端的问题就呈现在我们眼前了。
& & & & 在上一节我们说过Memory窗口有多种查看方式,我们将查看方式更改为int类型,图25就会以int的类型显示数据,如下所示:
图 28&&查看Memory内存窗口
& & & & 可以看到变量addr在内存中的4个地址组合成一个整体显示出了addr的数值,与变量的值是一样的都是,这样就方便我们查看内存数据了,不需要再考虑大小模式转换。不过这种方式是将内存中所有的数据都按照设置的类型显示,比如说当前显示类型为int型,那么几个char型、short型数也会被组合成int型来显示。
& & & & 长度超过1个Byte的类型都存在大小端的问题,比如说2Bytes的short型、unsigned short型也需要按照大小端的规则在内存中存放。
& & & & 有的处理器采用了小端模式,如PC机里的Intel X86 CPU,ARM等处理器,有的处理器则采用了大端模式,如PowerPC等处理器,还有一些处理器同时支持这2种模式,如TI的一些DSP处理器,可以选择使用其中的一种模式。
& & & & 对于8bits的51单片机来说硬件每次只能读写一个Byte的数据,不存在大小端模式的概念,但它的C语言却是能支持16bits的int型变量,这就需要使用2个地址存放数据,这也会涉及到变量的存放规则,比如说它的一个16bits的int型变量值为0x1234,地址是0x40和0x41,其中0x12被存储在0x40地址,0x34被存储在0x41地址,从这点来看好像是大端模式,但这并不是我们前面介绍过的大端模式。原因在于51单片机对16bits数据读写时是使用了2条机器指令,每条机器指令会有一个地址与之对应,可以认为是重复了2次对8bits数据的操作组成了一次对16bits数据的操作,对于硬件来说,看不到16bits的数据,只能看到8bits的数据,数的高低位与地址的对应关系是由编译器决定的,而不是由硬件决定的。而对于本手册所使用的ARM处理器来说,对16bits数据读写时只使用1条机器指令,这条指令只对应一个地址,而一个地址只对应8bits数据,因此这就需要使用1个地址存储2个地址的数据,这就涉及到了大小端模式问题,数的高低位与地址的对应关系是由硬件决定的,编译器根本插不上手。
& & & & 因此说51单片机是不存在大小端模式的,它所表现出的大小端是编译器的大小端,是编译器安排了数的存储模式,与处理器无关。
& & & & 除了在数据存储时会体现大小端的概念,在数据传输时也会存在大小端的问题,数据传输是从一个处理器发送到另一个处理器的过程,尽管物理层中的数据不全是以Byte为单位进行传输的,但数据在收发两端处理器中仍然是以Byte为单位进行管理的,这就会涉及到大小端问题,比如说处理器A中有一个int型的变量addr,它的值为0x,需要将这个值发送给处理器B,如果按照从数值高位到低位的顺序发送,那么发送出的数据为0x12-&0x34-&0x56-&0x78,接收端处理器B也按同样的顺序接收到这4个Bytes的数据,但问题也来了,处理器B不知道处理器A发送的顺序,如果按照从高位到低位的顺序组合,那么接收到的数据就是0x,如果按照从低位到高位的顺序组合,那么接收到的数据就是0x,这就出错了,因此在网络传输中需要收发双方约定好发送的顺序。
& & & & 数据发送时一般会按照内存地址增长的顺序发送数据,接收数据时也会按照内存地址增长的顺序存放数据,这称之为网络字节序,对于按大端模式存放的数来说,正好是从数的高位向低位的发送过程,因此网络字节序也称为大端字节序。比如说发送端处理器A是大端模式的,它有一个int型的变量a,它的数值为0x,地址为0xx2000020B,那么数&#就会存放在地址0x中,数&#就会存放在地址0x中,数&#就会存放在地址0x2000020A中,数&#就会存放在地址0x2000020B中,按照网络字节序的顺序发送,发送端就会按照0x12-&0x34-&0x56-&0x78的顺序发送数据,与数&#45678的写法是一致的。如果接收端处理器B将这4个Bytes的数据按照网络字节序存入0xx地址中,那么数&#就会存放在地址0x中,数&#就会存放在地址0x中,数&#就会存放在地址0x中,数&#就会存放在地址0x中,如果这4个地址是int型变量b的内存空间,那么对于大端模式的处理器B来说变量b的值就是0x,这样就实现了数值传输。当然,如果收发双方都约定使用小端模式来收发数据也是可以的,只要收发端使用相同的字节序就可以正确收发数据。
收发端使用相同的字节序,但收发端处理器的端模式不同也会有问题,来看下表,收发双方采用不同的大小端通过网络字节序发送int型数据:
表 7&&网络传输中收发端字节序对数据传输的影响
可以看到,尽管采用了相同的传输字节序,但收发两端处理器的字节序不同也会导致收发的数据不一致,解决这个问题的方法是发送端在发送前需要将发送的数据从处理器所使用的端模式转换成传输字节序,接收端在接收后需要将接收的数据从传输字节序转换成处理器所使用的端模式,来看下表:
表 8&&网络传输中收发端字节序的修改
& & & & 在linux中使用了htonl、ntohl、htons、ntohs这4个宏(在第6章讲宏)来完成网络字节序的转换,其中的h代表host,也就是处理器的端模式,n代表net,是网络字节序,l代表32bits数据,s代表16bits数据,那么htonl就是将32bits数据从处理器的端模式转换成网络字节序,ntohl是将32bits数据从网络字节序转换成处理器的端模式,htons是将16bits数据从处理器的端模式转换成网络字节序,ntohs是将16bits数据从网络字节序转换成处理器的端模式。
& & & & 在设计芯片管脚的硬件连接中也会存在大小端的问题,比如说在两块芯片间使用32bits并行数据线传输数据,两块芯片对高低数据线的定义上也会出现大小端模式的问题,这里就不详细阐述了。
& & & & 上述三种会产生大小端问题的场景都有一个共性,那就是破坏了数据的黑盒结构,不是由同一个执行单元对黑盒进行操作,而是由多个执行单元对黑盒进行操作,多个执行单元对黑盒内的理解不一致就会产生大小端问题。
&&C语言深度剖析&&
http://bbs.chinaunix.net/thread--1.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:55179次
排名:千里之外
原创:18篇
(1)(1)(1)(4)(6)(9)(1)(3)

我要回帖

更多关于 排序时间是什么意思 的文章

 

随机推荐