您的位置:首页 > 其它

字节存放顺序:大尾,小尾

2015-07-12 20:50 176 查看
字节存放顺序:大尾,小尾

字节存放有大尾和小尾之分。如果对应数据的高字节存放在低地址就是大尾,反之,高字节存放在高地址的就是小尾。

比如 short int a = 0x1234

大尾存放时:

偏移地址 存放内容

0x0000 0x12

0x0001 0x34

小尾存放:

偏移地址 存放内容

0x0000 0x34

0x0001 0x12

同样的如果数据是32位、64位也就是可以类推。

判断一个机器是大尾还是小尾我们可以通过程序进行测试:

#include <</SPAN>stdio.h>

#include <</SPAN>stdlib.h>

int main(void)

{

short int a = 0x1234;

char *p = (char *)&a;

printf("p=%#hhx\n", *p);

if (*p == 0x34) {

printf("little
endian\n");

} else if (*p == 0x12) {

printf("big
endia\n");

} else {

printf("unknown
endia\n");

}

return 0;

}

在网络上传输数据我们采用的都是大尾。这就存在字节顺序的相互转换。

下面定义一个宏可以对16位数据进行字节转换

#define sw16(x) \

((short)( \

(((short)(x) & (short)0x00ffU) <</SPAN><</SPAN>
8 ) | \

(((short)(x) & (short)0xff00U) >> 8 ) ))

假设这里x=0xaabb

(short)(x) & (short)0x00ffU 这里的与操作将16位数据x的高8位置为0得到0x00bb,然后在左移8位就得到了0xbb00

同理(short)(x) & (short)0xff00U >> 8 就得到了 0x00aa

最后将0xbb00 和 0x00aa 进行或运算就实现了高字节和低字节的相会交换。

关于字节顺序的交换我们可以参考include/linux/byteorder/ 下的文件swab.h和swabb.h中的定义。
转自: http://blog.chinaunix.net/uid-20753645-id-1877901.html

1.大尾(big_endian)小尾(little_endian)的问题

基于Web的测试软件是由C++数据采集服务器程序和客户端Java显示程序两部分构成,前者用C++,后者Java语言,存在数据移植问题。因为在计算机系统中,当包含数字的二进制文件从一个结构移到另一结构时,就出现大尾小尾问题。不同CPU在多字节数(如四字节int)存储时有两种方法,一种方法叫小尾(little_endian),数据的低字节被放置在连续存储区的首位,另一种方法叫大尾(big_endian),数据的高字节被放置在连续存储区的首位。Intel 80×86家族处理器是最后一个仍然坚持小尾的主要结构。所有其他的CPU结构(Motorola
680×0和所有RISC芯片)或者是纯粹的大尾或者是既适应大尾也适应小尾,大尾被认为是更符合逻辑的方法)。当数字由小尾处理器写入文件然后又由大尾处理器读取(或者倒过来)时,数字就会被搞乱(除了0和-1)。

目前在笔者参与的项目中平台中心的GM Server是C语言实现的,而我们这边的GM client为Java实现的,自然需要考虑这个通信时的大小尾转换,主要涉及short,int,long类型,String,byte类型不需要转换.

2.类型字节大小的问题

C语言中的基本类型如下:

类型
定义
说明
BYTE
typedef unsigned char BYTE
单字节
WORD
typedef unsigned short WORD
双字节无符号整数
SWORD
typedef signed short SWORD
双字节符号整数
DWORD
typedef unsigned int DWORD
四字节无符号整数
SDWORD
typedef signed int SDWORD
四字节符号整数
Java的八种基本数据类型如下:

byte 1字节

short 2字节

int 4字节

long 8字节 (C语言中是4字节)

char 2字节(C语言中是1字节)

float 4字节

double 8字节

boolean bool; false/true

3 综合:

大尾小尾转换举例:

比如有个Int Java类型十六进制

00 00 80 01 (大尾)

转换成C语言时为:

01 80 00 00 (小尾)

比如short 类型

40 02 (大尾)

02 40 (小尾)

一般比如Mina通讯框架都有大小尾转换的现成的API可供调用

IOBuffer.order(ByteOrder.LITTLE_ENDIAN) //转成了小尾

IOBuffer.order(ByteOrder.BIG_ENDIAN) //转成了大尾

JAVA 默认 大尾

C 默认小尾

AS 默认大尾

byte[]数组的翻转可以使用ArrayUtils.reverse(byte[]) 结合关于数据窄化的介绍就可以完成大小尾的转换了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: