码迷,mamicode.com
首页 > 其他好文 > 详细

字节序

时间:2015-03-30 22:58:52      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:

现代计算机一般采用字节(Octet or Byte)作为逻辑寻址单位,当物理长度大于一个字节时,就要区分字节顺序(Byte Order)。例如在C语言中,除了8bit char外,还有16bit的short和32bit的int;此外对于大于8位的处理器,如16位或32位处理器,由于寄存器宽度大于一个字节,也存在多个字节排列的问题。常见的字节顺序有两种:Big-Endian和Little-Endian。

 

大端序(Big-Endian)即是将其最高有效位(Most Sigificant Bit)放在内存的低地址端,最低有效位(Little Sigificant Bit)放在内存的高地址端;小端序(Little-Endian)则恰好相反。若将整型数据0x12345678存入内存,其在不同的系统中表示如下:

0 --> 31

0x12

0x34

0x56

0x78

Big-Endian

0 --> 31

0x78

0x56

0x34

0x12

Little-Endian

 

由上可知,采用大小端模式对数据进行存放的主要区别在于存放的字节顺序。通常来讲,Little-Endian最符合人类思维,即将低位值放在内存地址小的地方,将高位值放在内存地址大的地方。而Big-Endian更适合计算机处理。

 

对于一台机器字节序的判断,有几种方法可以使用:

  • union的所有成员在内存中的存放是从低地址到高地址,利用此特性,可以获得CPU对内存采用的策略是Little-Endian还是Big-Endian
union NUM {
    char cval;
    int ival;
} num;

num.ival = 0x12345678; 

if (num.cval == 0x12)
    printf("It‘s Big-Endian.\n");

else if (num.cval == 0x78)
    printf("It‘s Little-Endian.\n");

else
    printf("Cant‘t tell the type of machine.\n");
  • 也可通过读取同一地址的int数据和char数据来判断
int ival = 0x1234;
char cval = *(char *)&ival;
printf("cval = 0x%x\n", cval);

 

在通用的处理器中,x86体系结构是Little-Endian,而ARM通常采用的是Big-Endian。此外,网络字节序采用的是Big-Endian,它是TCP/IP中规定好的一种数据表示格式,与具体的CPU无关,从而可以保证数据在不同主机之间传输时能够被正确解释。因此在进行网络编程时,通常需要进行大小端字节序的转换。

 

为了进行字节序的转换,BSD Socket提供了以下4个转换函数:

htons( ) 将unsigned short类型从主机序转换到网络序

htonl( ) 将unsigned long类型从主机序转换到网络序

ntohs( ) 将unsigned short类型从网络序转换到主机序

ntohl( ) 将unsigned long类型从网络序转换到主机序

在使用Little-Endian的系统中,这些函数会把字节序进行转换,而在Big-Endian的系统中,这些函数会定义成宏。

 

除去大端序和小端序外,还有混合序(Meddle-Endian),它的顺序更为复杂。仍以整型数据0x12345678为例,它在Meddle-Endian系统中的表示为:

0 --> 31

0x34

0x12

0x78

0x56

 

可将这个32bit的数据以16bit分割,前16bit与后16bit以Big-Endian排列;在16bit内部,以Little-Endian排列。这个例子仅作了解。

 

大端和小端排序是以字节为单位的,但CPU在存储一个字节时,其内部的8个bit之间的排列也有大小端之分。下面以位域(Bit field)为列以作说明。

union {
    struct {
        unsigned char c1:2;
        unsigned char c2:3;
        unsigned char c3:3;
    } st;
    unsigned char ch;
} uval;

uval.ch = 0x64;
printf("c1 = %d\n", uval.st.c1);
printf("c2 = %d\n", uval.st.c2);
printf("c3 = %d\n", uval.st.c3);

return 0;        

 代码中0x64的二进制为0110 0100,若系统为小端序,其在一个字节内的排序为:

0 --> 7

0

0

1

0

0

1

1

0

 

程序运行结果显示,c1 = 0,c2 = 1,c3 = 3。即c1取00,c2取100,c3取110。

本例采用的是x86_64和GCC实现。

字节序

标签:

原文地址:http://www.cnblogs.com/0xceff/p/4308973.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!