字节内存储顺序

  source address : http://www.linuxjournal.com/article/6788?page=0,1 

  1.Byte Order: the Endianness

  Two types of endianness exist, big endian and little endian. Big endian refers to the method that stores the most significant byte of an integer at the lowest byte address. Little endian is the opposite; it refers to the method of storing the most significant byte of an integer at the highest byte address.

  Bit order usually follows the same endianness as the byte order for a given computer system. That is, in a big endian system the most significant bit is stored at the lowest bit address; in a little endian system, the least significant bit is stored at the lowest bit address.

  2.Endianness of Bus

  The bus we refer to here is the external bus we showed in the figure above. We use PCI as an example below. The bus, as we know, is an intermediary component that interconnects CPUs, devices and various other components on the system. The endianness of bus is a standard for byte/bit order that bus protocol defines and with which other components comply.

  Take an example of the PCI bus known as little endian. It implies the following: among the 32 address/data bus line AD [31:0], it expects a 32-bit device and connects its most significant data line to AD31 and least significant data line to AD0. A big endian bus protocol would be the opposite.

  For a partial word device connected to bus, for example, an 8-bit device, little endian bus-like PCI specifies that the eight data lines of the device be connected to AD[7:0]. For a big endian bus protocol, it would be connected to AD[24:31].

  In addition, for PCI bus the protocol requires each PCI device to implement a configuration space. This is a set of configuration registers that have the same byte order as the bus.

      3.Endianness of Network Protocols

  The endianness of network protocols defines the order in which the bits and bytes of an integer field of a network protocol header are sent and received. We also introduce a term called wire address here. A lower wire address bit or byte always is transmitted and received in front of a higher wire address bit or byte.

  The endianness of NIC devices usually follow the endianness of the network protocols they support, so it could be different from the endianness of the CPU on the system. Most network protocols are big endian;
  

  4. bit field and memory storage
ex:

typedef struct {

    unsigned int    b1:1;

    unsigned int    b2:8;

    unsigned int    b3:7;

    unsigned int    b4:8;

    unsigned int    b5:7;

    unsigned int    b6:1;} BIT_STRUCT;

      Suppose you wanted to use the same structure definition to read in bit field data on an big endian

and little endian machine and you were willing to massage the data on input before mapping the structure

to it. Suppose we started with big endian data that was 32 bits long.


Memory layout big/little endian:

Let the start of memory be adressed as below for a big endian machine...

              byte 0          byte 1       byte 2       byte 3

    • |B31....B25     |B24....B16         |B15....B8   |B7....B0           |   Big endian
    • |B7....B0         ||B15....B8          ||B24....B16||B31....B25      |   Little endian
    • |b1[0],b2[7:1] | b2[0], b3[6:0]   | b4[7:0]       | b5[6:0] , b6[0]| physical layout when bigend generates.

  总结上面几点:

    通常来说,对于big endian machine,它的字节序与比特序都是大端,即低地址存高位字节,bit0存高位二进制码;

现举一个例子,比特域顺序是从左到右存   

ex:

union {

  struct {

   unsigned char a:1;

   unsigned char b:3;

   unsigned char c:2;

   }s;

  unsigned char x;

 }tb;

 tb.x = 0;

 tb.s.a = 0;

 tb.s.b = 2;

 tb.s.c = 1;   



 tb.x = ?

 

left -- > right

b0 b1 b1 b3 b4 b5 b6 b7

 so
    little-endian bitfield: ascending order in byte(left to right) 

 tb.x = 0 010 10 00 = bin(0001 0100) = 0x14 = 20

        0  2   1 padding

    big-endian bitfield : descending order in byte (right to left)

 tb.x = 0 010 01 00 = bin(0010 0100)=0x24 = 36

        0 2  1 padding

  test result:
     avr32 studio(黑色甲壳虫icon) :

big-endian bitfield : tb.x = 36

     linux gcc:

little-endian bitfield :  tb.x = 20

    avr atmel studio 6.0:

little-endian bitfield :  tb.x = 20

 another example:

typedef struct

        {

            byte                      ndd_p          : 4;

            byte                      ndd_net           : 4;

            word                      pref_field    : 9;

            word                      sbits            : 3;

            word                      pref_field_length : 4;

        } s;

    

    s stru;

    stru.ndd_p = 2;                            0010

    stru.ndd_net = 1;                          0001

    stru.pref_field = 0x187;                   1 1000 0111

    stru.sbits = 2;                            010

    stru.pref_field_length = 0x06;             0110

little endian machine:

|<--                  32                    -->|

|<-- 8 -->| byte align|<-  9  ->| |<-3->||<-4->|
0100 1000 0000 0000 1110 0001 1 010 0110 ndd_p ndd_net padding pref_field sbits len 0001 0010 0000 0000 1000 0111 0110 0101 0x 12 00 87 65
   b0 ... b7

big endian machine:

|<--                  32                    -->|

|<-- 8 -->|           |<-  9  ->| |<-3->||<-4->|
0010 0001 0000 0000 1 1000 0111 010 0110 ndd_p ndd_net padding pref_field sbits len 0010 0001  0000 0000 1100 0011 1010 0110 0x 21 00 c3 a6
   b0 ... b7

另一种理解方式,比较直观

b7 ... b0 b7 ... b0 ...

byte 0        byte 1      byte 2     byte 3

b31 ... b24 b23 ... b16 b15 ... b8 b7 ... b0      big endian

b7 ... b0   b15 ... b8 b23 ... b16 b31 ... b24    little endian

|<--                           32                          -->|

|<-- 8 -->|              |<-   9   ->|           |<-3->||<-4->|

 0010 0001     0000 0000 1 1000 011  1             010   0110    big endian

 ndd_p ndd_net  padding field_high8 field_low1     sbits  len

 0010 0001  0000 0000  1100 0011  1010 0110

 0x   21       00         c3         a6    

                                                                 big endian member layout : from high bit end to low bit end  -> b31 to b0



 0001 0010   0000 0000  1000 0111 0110  010     1                little endian
ndd_net ndd_p paddind  field_low8 len  sbits field_high1 0x
12 00 87 65 little endian member layout : from low to high -> b0 to b31 high -- > low 其它共同点:高bit位存高位值,不因大小端改变而变

 

 附

 
// bit_fields1.cpp

struct Date

{

   unsigned nWeekDay  : 3;    // 0..7   (3 bits)

   unsigned nMonthDay : 6;    // 0..31  (6 bits)

   unsigned nMonth    : 5;    // 0..12  (5 bits)

   unsigned nYear     : 8;    // 0..100 (8 bits)

};



int main()

{

}

The conceptual memory layout of an object of type Date is shown in the following figure.

Memory Layout of Date Object

字节内存储顺序

Note that nYear is 8 bits long and would overflow the word boundary of the declared type, unsigned int. Therefore, it is begun at the beginning of a new unsigned int. It is not necessary that all bit fields fit in one object of the underlying type; new units of storage are allocated, according to the number of bits requested in the declaration.

Microsoft Specific

The ordering of data declared as bit fields is from low to high bit, as shown in the figure above.

END Microsoft Specific

If the declaration of a structure includes an unnamed field of length 0, as shown in the following example,

 
// bit_fields2.cpp

struct Date

{

   unsigned nWeekDay  : 3;    // 0..7   (3 bits)

   unsigned nMonthDay : 6;    // 0..31  (6 bits)

   unsigned           : 0;    // Force alignment to next boundary.

   unsigned nMonth    : 5;    // 0..12  (5 bits)

   unsigned nYear     : 8;    // 0..100 (8 bits)

};



int main()

{

}

the memory layout is as shown in the following figure.

Layout of Date Object with Zero-Length Bit Field

 

 

你可能感兴趣的:(内存)