Big Endian 和 Little Endian

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/henulwj/article/details/48195237

最近看到一篇文章中有涉及大端存储和小段存储,不得其理,只记得本科计算机组成原理中有讲到过,然后就找到一些资料重新学习了一下。

起因

为什么会出现两种不同的存储方案呢,起因是由于当时CPU在涉及开发时,有两种系列的CPU

  • PowerPC的CPU
  • x86的CPU

PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?

big endian是指低地址存放最高有效字节 MSB (Most Significant Byte, 最高有效字节)
little endian是低地址存放最低有效字节 LSB (Least Significant Byte, 最低有效字节)

简单点来说,本科老师教过的口诀:

小端口诀: 高高低低 -> 高字节在高地址, 低字节在低地址
大端口诀: 高低低高 -> 高字节在低地址, 低字节在高地址

举例

如果我们将test = 0x1234abcd写入到以0x0000开始的内存中,则结果为

addr big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12

test变量存储的是的0x10这个地址,
那编译器怎么知道是读四个字节呢? -> 根据变量test的类型可知这个变量占据4个字节.
那编译器怎么读出这个变量test所代表的值呢? -> 这就根据是little endian还是big endian来读取

比较

Big Endian
判别一个数的正负很容易,只要取offset0处的一个字节就能确认。
Little Endian
长度为1,2,4字节的数,排列方式都是一样的,数据类型转换非常方便。

一般来说,采用大端方式 进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。

参考

http://blog.csdn.net/andkylee/article/details/5361078
http://blog.csdn.net/sunshine1314/article/details/2309655

展开阅读全文

Little EndianBig Endian 之来由(很有意思!)

08-12

术语"little endian(小端)"和"big endian(大端)"来自于Jonathan Swift的<>, 其中交战的两个派别无法就应该从哪一端----小端还是大端----打开一个半熟的鸡蛋达成一致. 就像鸡蛋的问题一样, 没有技术原因来选择字节顺序规则, 因此争论退化成为关于社会政治论题的口角.rnrn下面就是Jonathan Swift在1726年如何描述大, 小端之争的历史的:rnrn "......我下面要告诉你的是, Lilliput和Blefuscu这两大强国在过去三十六个月里一直在苦战. 战争开始是由于以下的原因: 我们大家都认为, 吃鸡蛋前, 原始的方法是打破鸡蛋较大的一端, 可是当今的皇帝的祖父小时候吃鸡蛋, 一次按古法打鸡蛋时碰巧将一个手指弄破了, 因此他的父亲, 当时的皇帝, 就下了一道敕令, 命令全体臣民吃鸡蛋时打破鸡蛋较小的一端, 违令者重罚. 老百姓们对这项命令极为反感. 历史告诉我们, 由此曾发生过六次叛乱, 其中一个皇帝送了命, 另一个丢了王位. 这些叛乱大多都是由Blefuscu的国王大臣们煽动起来的. 叛乱平息后, 流亡的人总是逃到那个帝国去寻求避难. 据估计, 先后几次有一万一千人情愿受死也不肯去打破鸡蛋较小的一端. 关于这一争端, 曾出版过几百本大部著作, 不过大端派的书一直是受禁的, 法律也规定该派的任何人不得做官." (此段译文摘自网上蒋剑锋译的<>第一卷第4章.)rnrn 在他那个时代, Swift是在讽刺英国(Lilliput)和法国(Blefuscu)之间持续的冲突. Danny Cohen, 一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序, 后来这个术语就被广泛接纳了.rnrn第一次发贴, 希望版主不会删...... 论坛

[原创分享]ANSI、UTF-8、Unicode(little endian)、Unicode big endian的互相转换

11-15

[code=SQL]ANSI、UTF-8、Unicode(little endian)、Unicode big endian的互相转换rn*----------------------------------------------------------------rn*!* 作者:十豆三rn*!* 日期:2011-11-15rn*!* vfp版本:vfp9.0(SP2 7423)rn*!* 操作系统:Windows XP(SP3)rnrn*!* ANSI:rn*!* ANSI字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\0结尾,常用于txt文本文件rnrn*!* Unicode:rn*!* Unicode字符串每个字符(汉字、英文字母)都占2个字节,以2个连续的\0结尾,rn*!* NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;rn*!* 所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicode。rn*!* little endian:最低位地址存放低位字节,可称低位优先,内存从最低地址开始按顺序存放(低数位数字先写)。最低位字节放最前面。rn*!* big endian: 最低位地址存放高位字节,可称高位优先,内存从最低地址开始按顺序存放(高数位数字先写)。最高位字节放最前面。rnrn*!* UTF8:rn*!* UTF8是Unicode一种压缩形式,英文A在unicode中表示为0x0041,老外觉得这种存储方式太浪费,rn*!* 因为浪费了50%的空间,于是就把英文压缩成1个字节,成了utf8编码,但是汉字在utf8中占3个字节,rn*!* 显然用做中文不如ANSI合算,这就是中国的网页用作ANSI编码而老外的网页常用utf8的原因。rnrn*!* 签名BOM:rn*!* BOM 是 Byte Order Mark 的缩写(字节顺序标记),是编码方案里用于标识编码的标准标记。rn*!* ANSI 文件没有 BOMrn*!* UTF-8 文件的 BOM 为:EF BB BF,不过 UTF-8 文件可以有 BOM,也可以没有 BOMrn*!* Unicode little endian 文件的 BOM 为:FF FErn*!* Unicode big endian 文件的 BOM 为:FE FFrnrn*!* vfp 的 UI 不支持 unicode,但可以读写 unicode 文件。rnrn*--------------------------------------------------------------------------------rn*-- 字符串保存为 ANSI、UTF-8、Unicode(little endian)、Unicode big endian 格式文件rnrnlcStr='abc十豆三123'rnrn*-- 生成的 ANSI编码文件.txt:12字节(每个英文和数字占1个字节,每个汉字占2个字节)rn=Strtofile(lcStr,'c:\ANSI编码文件.txt')rnrn*--生成的 UTF-8编码文件.txt:18字节(每个英文和数字占1个字节,每个汉字占3个字节)rn=Strtofile(Strconv(lcStr,9),'c:\UTF-8编码文件.txt',4)rnrn*-- 生成的 Unicode编码文件.txt:20字节(每个英文、数字及汉字占2个字节,另加上BOM长度2)rn=Strtofile(Strconv(lcStr,5),'c:\Unicode编码文件.txt',2)rnrn*-- 生成的 Unicode big endian 编码文件.txt:20字节(每个英文、数字及汉字占2个字节,另加上BOM长度2)rnlcUnicodeStr=Strconv(lcStr,5)rnlnStrLen=Len(lcUnicodeStr)rnlcUnicodeBigStr=''rnFor lnI=1 To lnStrLen Step 2rn lcUnicodeBigStr=lcUnicodeBigStr+Substr(lcUnicodeStr,lnI+1,1)+Substr(lcUnicodeStr,lnI,1)rnEndforrn=Strtofile(Chr(0xFE)+Chr(0xFF)+lcUnicodeBigStr,'c:\Unicode big endian编码文件.txt')rnrn*------------------------------------------------------------------------------rn*-- ANSI 格式文件 转 UTF-8、Unicode(little endian)、Unicode big endian 格式文件rnrn*-- ANSI To UTF-8 (文件头写入UTF-8文件的BOM)rn=Strtofile(Strconv(Filetostr('c:\ANSI编码文件.txt'),9),'c:\UTF-8编码文件.txt',4)rnrn*-- ANSI To Unicode (文件头写入Unicode文件的BOM)rn=Strtofile(Strconv(Filetostr('c:\ANSI编码文件.txt'),5),'c:\Unicode编码文件.txt',2)rnrn*-- ANSI To Unicode big endian (文件头写入Unicode big endian文件的BOM)rnlcUnicodeStr=Strconv(Filetostr('c:\ANSI编码文件.txt'),5)rnlnStrLen=Len(lcUnicodeStr)rnlcUnicodeBigStr=''rnFor lnI=1 To lnStrLen Step 2rn lcUnicodeBigStr=lcUnicodeBigStr+Substr(lcUnicodeStr,lnI+1,1)+Substr(lcUnicodeStr,lnI,1)rnEndforrn=Strtofile(Chr(0xFE)+Chr(0xFF)+lcUnicodeBigStr,'c:\Unicode big endian编码文件.txt')rnrn*------------------------------------------------------------------------------rn*-- UTF-8 格式文件 转 ANSI、Unicode(little endian)、Unicode big endian 格式文件rnlcUtf8Str=Filetostr('c:\UTF-8编码文件.txt')rnIf Left(lcUtf8Str,3)=Chr(0xEF)+Chr(0xBB)+Chr(0xBF)rn lcUtf8Str=Substr(lcUtf8Str,4) && 去掉 UTF-8 的 BOMrnEndifrnrn*-- UTF-8 To ANSI (ANSI文件没有签名BOM)rn=Strtofile(Strconv(lcUtf8Str,11),'c:\ANSI编码文件.txt')rnrn*-- UTF-8 To Unicode (文件头写入Unicode文件的BOM)rn=Strtofile(Strconv(lcUtf8Str,12),'c:\Unicode编码文件.txt',2)rnrn*-- UTF-8 To Unicode big endian (文件头写入Unicode big endian文件的BOM)rnlcUnicodeStr=Strconv(lcUtf8Str,12)rnlnStrLen=Len(lcUnicodeStr)rnlcUnicodeBigStr=''rnFor lnI=1 To lnStrLen Step 2rn lcUnicodeBigStr=lcUnicodeBigStr+Substr(lcUnicodeStr,lnI+1,1)+Substr(lcUnicodeStr,lnI,1)rnEndforrn=Strtofile(Chr(0xFE)+Chr(0xFF)+lcUnicodeBigStr,'c:\Unicode big endian编码文件.txt')rnrn*------------------------------------------------------------------------------rn*-- Unicode(little endian) 格式文件 转 ANSI、UTF-8、Unicode big endian 格式文件rnrnlcUnicodeStr=Filetostr('c:\Unicode编码文件.txt')rnIf Left(lcUnicodeStr,2)=Chr(0xFF)+Chr(0xFE)rn lcUnicodeStr=Substr(lcUnicodeStr,3) && 去掉 Unicode 的 BOMrnEndifrnrn*-- Unicode To ANSI (ANSI文件没有签名BOM)rn=Strtofile(Strconv(lcUnicodeStr,6),'c:\ANSI编码文件.txt')rnrn*-- Unicode To UTF-8 (文件头写入UTF-8文件的BOM)rn=Strtofile(Strconv(lcUnicodeStr,10),'c:\UTF-8编码文件.txt',4)rnrn*-- Unicode To Unicode big endian (文件头写入Unicode big endian文件的BOM)rnlnStrLen=Len(lcUnicodeStr)rnlcUnicodeBigStr=''rnFor lnI=1 To lnStrLen Step 2rn lcUnicodeBigStr=lcUnicodeBigStr+Substr(lcUnicodeStr,lnI+1,1)+Substr(lcUnicodeStr,lnI,1)rnEndforrn=Strtofile(Chr(0xFE)+Chr(0xFF)+lcUnicodeBigStr,'c:\Unicode big endian编码文件.txt')rnrn*------------------------------------------------------------------------------rn*-- Unicode big endian 格式文件 转 ANSI、UTF-8、Unicode(little endian) 格式文件rnrnlcUnicodeBigStr=Filetostr('c:\Unicode big endian编码文件.txt')rnIf Left(lcUnicodeBigStr,2)=Chr(0xFE)+Chr(0xFF)rn lcUnicodeBigStr=Substr(lcUnicodeBigStr,3) && 去掉 Unicode big endian 的 BOMrnEndifrnlnStrLen=Len(lcUnicodeBigStr)rnlcUnicodeStr=''rnFor lnI=1 To lnStrLen Step 2rn lcUnicodeStr=lcUnicodeStr+Substr(lcUnicodeBigStr,lnI+1,1)+Substr(lcUnicodeBigStr,lnI,1)rnEndforrnrn*-- Unicode big endian To ANSI (ANSI文件没有签名BOM)rn=Strtofile(Strconv(lcUnicodeStr,6),'c:\ANSI编码文件.txt')rnrn*-- Unicode big endian To UTF-8 (文件头写入UTF-8文件的BOM)rn=Strtofile(Strconv(lcUnicodeStr,10),'c:\UTF-8编码文件.txt',4)rnrn*-- Unicode big endian To Unicode (文件头写入Unicode文件的BOM)rn=Strtofile(lcUnicodeStr,'c:\Unicode编码文件.txt',2)[/code] 论坛

奇怪的little/big endian问题,请大家发言

06-21

进来看帖子的朋友都帮着up一下,让帖子别沉了.rnrn问题描述:rn从网络上某window XP的PC上收到一串内容 buffer, 表示为16进制如下: (共11 bytes)rn00 b9 0b ,01 00 00 00, 00 04 00 00rn ----->rn内存中看到的内容如上,从左往右是内存地址增加方向.rn现在有个指针指向 "01" 的位置. 用char *data表示.rn这个data的内容是要赋值给一个结构的.rnstruct testrnrn int a;rn int b;rn;rn即rnvoid fun(char *data, int datalen)rnrnstruct test *t = (struct test*)data; //data指向"01"所在的地方.rnprintf("result, a: 0x%08x, b: 0x%08x\n", t->a, t->b);rnprintf("result, a: %d, b: %d\n", t->a, t->b);rnrn传进去的 datalen = 8;rnrn得到的结果应该是rnresult, a: 0x00000001, b: 0x00000400rnresult, a: 1, b: 1024rnrn也就是说,我要得到"01"后面, 每4个字节的内容到一个int中.rnrn但实际运行的结果却不是如此. 实际的结果是:rnresult, a: 0x010bb900, b: 0x00000000rnresult, a: 17545472, b: 0rnrn即我本来想得到的数据应该为"01" 后面的内容,但实际的结果却是走到了"01"左边的几个字节上.rnb的内容也变成了"01" 后面的"00"的那4个字节.rnrn以上的代码是运行在某ARM开发板上的结果.rn开发板上sizeof(int)是 4rn即4个字节表示一个整数.rnsizeof(struct test)为8rndata的指针point为0x09...87, 后面的两位为87. 中间的没记下.rnrn后来经过改写:rnstruct test tmp;rnmemcpy( &tmp, data, sizeof(sturct test));rnprintf("result, a: 0x%08x, b: 0x%08x\n", tmp->a, tmp->b);rnprintf("result, a: %d, b: %d\n", tmp->a, tmp->b);rn使用memcpy 来复制内存内容后,结果输出正确. memcpy应该是把data右边的内容copy正确到了tmp中.问题最后是解决了的.rnrnrn疑问:rn1. 有人说不是little/big endian的问题,是数据结构struct test对齐的问题. 大家什么意见?rn说是从"data的指针point为0x09...87, 后面的两位为87." 看出的问题. 不被4整除? 好像不是这样吧.大家聊聊自己的看法.rn2. 错误出现时, 取到的结果是rna: 01 0b b9 00rnb: 00 00 00 00rn也就是在字串被这样处理了rn00 b9 0b 01, 00 00 00 00, 04 00 00rn即data指向的"01"被当成了高位.低位在它的左边. 即得到的是"01"加上它左边的3个字符,而不是右边的3个字符.rn不知是否这样解释?rn但这个解释好像很奇怪喔. 怎么跑到了左边?rnrn3. 一般大家讨论的情况可能只会涉及到rn01 00 00 00, 00 04 00 00rn这个的排列的内容的含义:rn如:rn一种排列为: rn01 00 00 00rn00 04 00 00 rn另一种排列为:rn00 00 00 01rn00 00 04 00rnrn但我这里遇到的是实际运行系统中的现象. 和这个讨论有点不同.rn请大家就我的实际例子来讨论.rn4. 难道是内存中数据被其他的代码"踩到", 出错了?rn5. 不知道代码中其他地方还有没有这样的后患.呵呵.rnrn相关知识,来自网络:rn1. Big-Endian 和 Little-Endian 翻译为: 大端,小端rn2. Big-Endian 和 Little-Endian rn这两个术语来自于 Jonathan Swift 的《《格利佛游记》其中交战的两个派别无法就应该从哪一端--小端还是大端--打开一个半熟的鸡蛋达成一致。:)rn在那个时代,Swift是在讽刺英国和法国之间的持续冲突,Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了rn摘自《深入理解计算机系统》 rn3. 含义:rnbig endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。rnlittle endian:最低字节在最低位,最高字节在最高位,反序排列。rn没记错的话,除了moto的68K系列和dec的sparc是big endian外,常见的cpu都是little endian。ARM同时支持big和little,实际应用中通常使用little endian。rnrn欢迎大家讨论.rn进来看帖子的朋友都帮着up一下,让帖子别沉了. 论坛

没有更多推荐了,返回首页