大端 小端
http://blog.sina.com.cn/s/blog_6ffd3b5c0100mc4z.html
1. 小端
在bitstream的定義中,經(jīng)常見到這樣的定義
exam{
A:18 bit stream left bit first
B: 14 bit stream left bit first
}
在小端(little endian)系統(tǒng)中,上述32bit被讀入內(nèi)存,memory map如下
------------------------------------------------------------------------------------
| A7 ... A0 | A15 ... A8 | B5 ... B0 A17 A16 | B13 ... B6 |
????byte0????????byte1????????????byte2???????????byte3
low address --------------------------------> high address
-------------------------------------------------------------------------------------
NOTE:該處A0代表線路上最先到達(dá)的bit,A17代表最后到達(dá).
可見小端系統(tǒng)是一個(gè)移位性質(zhì)的寄存器,先到達(dá)的bit放在byte內(nèi)的高位地址。(所謂小端地址的定義是:most significant byte in high address。所以 0x01 0x02 0x03 0x04,代表的數(shù)據(jù)是0x04030201.同樣的道理,在字節(jié)內(nèi)部,物理地址高的bit代表高位。所以如果一個(gè)binary stream在字節(jié)中從左到右的順序是 10001010,那么它代表的byte數(shù)據(jù)應(yīng)該是0x51,而不是0x8A.)
可見,屬于同一個(gè)域A的數(shù)據(jù)在物理地址上面并不連續(xù)了。為了處理這個(gè)問(wèn)題,我們必須把這32bit數(shù)據(jù)變換為小端Byte順序,既
------------------------------------------------------------------------------------
| B13 ... B6 | B5 ... B0 A17 A16 | A15 ... A8 | A7 ... A0 |
????byte3 ???????????byte2 ???????????byte1 ??????byte0
low address --------------------------------> high address
-------------------------------------------------------------------------------------
這樣一來(lái),同一個(gè)域的數(shù)據(jù)在物理上就連續(xù)了。使用C語(yǔ)言bit field的定義
struct{
????UINT32 B:14;
????UINT32 A:18;
}
這樣 B 對(duì)應(yīng)了這個(gè)32bit結(jié)構(gòu)的低14bits, A 對(duì)應(yīng)了高18bits。編譯器只需要簡(jiǎn)單的截?cái)嘁莆痪涂梢蕴幚磉@兩個(gè)域了。
2. 大端
大端系統(tǒng)正好相反,在byte順序上是高位數(shù)據(jù)對(duì)應(yīng)least significant byte。在byte內(nèi)部靠近高位地址的bit對(duì)應(yīng)least significant bit.
數(shù)據(jù)到達(dá)內(nèi)存的時(shí)候
------------------------------------------------------------------------------------
| A0 ... A7 | A8 ... A15 | A16 A17 B0 ... B5 | B6 ... B13 |
????byte0????????byte1????????????byte2???????????byte3
low address --------------------------------> high address
-------------------------------------------------------------------------------------
大段在物理地址上和傳輸順序(文檔描述)一模一樣,比較容易理解。這也是大端結(jié)構(gòu)設(shè)計(jì)的初衷。
于是只需要在bit field聲明如下結(jié)構(gòu):
struct{
????UINT32 A:18;
????UINT32 B:14;
}
這樣就一目了然了。
3.總結(jié)
這些內(nèi)容如果不是經(jīng)常使用非常容易混淆,因?yàn)樾《诵枰袃蓚€(gè)轉(zhuǎn)換,首先是byte順序,其次是bit順序。使用的時(shí)候最好在pc上多做實(shí)驗(yàn)。
對(duì)于小端,我之前理解的有個(gè)誤區(qū),比如0x12345678
我認(rèn)為僅僅只字節(jié)的位置倒置,其實(shí)是這個(gè)數(shù)字的bit全部倒置,而c對(duì)一個(gè)字節(jié)內(nèi)的操作是不可見的,就是你以為是正序的,其實(shí)它是逆序的。
比如,int c = 5;
while(c) {
?? ? ? ?cout<<(c&1)<<endl;
?? ? ? ?c =c >>1;
?? ?}
我們發(fā)現(xiàn)字節(jié)是正序排列的,即0101。其實(shí)在內(nèi)存中bit是逆序排列的,1010,只是操作系統(tǒng)對(duì)我們隱藏了對(duì)bit的操作。
例如,對(duì)于這個(gè)題目:
typedef struct bitstruct
{
int b1:5;
int :2;
int b2:2;
} bitstruct;
void main()
{
bitstruct b;
memcpy(&b, "EMC EXAMINATION", sizeof(b));
printf("%d,\n", sizeof(b)); //輸出4
printf("%d, %d\n", b.b1, b.b2); //輸出5,-2
}
在內(nèi)存中存儲(chǔ)的是,0x45 4d 43 20
并且在每個(gè)字節(jié)內(nèi)的bit是逆序排列的
內(nèi)存分布
| 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | …… |
| E | M | |||||||||||||
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | …… |
b.b1是 10100,對(duì)其再次逆序,得00101,得5
b.b2 = 01,對(duì)其再次逆序是 10,取其補(bǔ)碼是-2
http://blog.csdn.net/ermuzhi/article/details/7940280
99規(guī)定int、unsigned int和bool可以作為位域類型,但編譯器幾乎都對(duì)此作了擴(kuò)展,允許其它類型類型的存在。使用位域的主要目的是壓縮存儲(chǔ),其大致規(guī)則為:
1) 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個(gè)字段存儲(chǔ),直到不能容納為止;
2) 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲(chǔ)單元開始,其偏移量為其類型大小的整數(shù)倍;
3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實(shí)現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
4) 如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
5) 整個(gè)結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。
和結(jié)構(gòu)體一樣,位結(jié)構(gòu)體也是按照成員的最大長(zhǎng)度字節(jié)來(lái)對(duì)齊分配空間的。
測(cè)試:
struct test
{
char a:1;
char :2;
long b:3;
char c:2;
};
test t1;
int len=sizeof(t1);?//len=4,前兩個(gè)位域共用一個(gè)char空間,按第三個(gè)位域long擴(kuò)展為4字節(jié)空間,最后一個(gè)位域占用一個(gè)char空間,按最長(zhǎng)位域空間擴(kuò)展為4字節(jié)。
structtest
{
char f1 : 3;
short f2 : 4;
char f3 : 5;
};
test t1;
int len=sizeof(t1);?//len=2,第一位域占用一個(gè)char空間,按第二個(gè)位域short擴(kuò)展為2字節(jié)空間,最后一個(gè)位域占用一個(gè)char空間,按最長(zhǎng)位域空間擴(kuò)展為2字節(jié)。
如果位域上的整形范圍值是0,則下個(gè)位域從新的字節(jié)開始,前一字段后面空出的所有字節(jié)都不使用(即使是同類型的位域),如:
structbs
{
unsigned a:4;
unsigned :0; //?空域
unsigned b:4; // 從新字節(jié)開始存放
unsigned c:4;
} ;
sizeof(unsigned)== 4
上面這個(gè)位域定義中,a占第一字節(jié)的4位,第一個(gè)字節(jié)的后4位以及后面的3個(gè)字節(jié)都填0表示不使用,b從新的字節(jié)開始,占用4位,c占用4位。上面位結(jié)構(gòu)體大小為:8
struct test
{
char a:1;
char :2;
char b:3;
long c:2;
};
test t1;
int len=sizeof(t1); //len=4
struct test
{
char a:1;
char :2;
char b:3;
char c:2;
};
test t1;
int len=sizeof(t1); //len=1
{// test2
union V {
?? struct X {
????? unsigned char s1:2;
????? unsigned char s2:3;
????? unsigned char s3:3;
?? } x;
?? unsigned char c;
} v;
v.c = 100;
printf("%d", v.x.s3);?
}
結(jié)果:3,從低位開始分配位空間
?
#include??? <iostream>??
using?? namespace?? std;?
struct?? A????
{????
char?? t:4;????
char?? k:4;????
unsigned?? short?? i:8;????
unsigned?? long?? m;????
}????
;?
main()?
{????
struct?? A?? a;?
a.t= 'b ';?
cout??? < <?? a.t < <?? endl;?
??????????????
}
?
?
a.t = 'b';效果相當(dāng)于?a.t= 'b' & 0xf;
'b' --> 01100010
'b' & 0xf -->>00000010
所以輸出Ascii碼為2的特殊字符
?
下一個(gè)例子:
?
?
?union Test {
? ? char a[5];
? ? short b;
};
int main()
{
Test t;
? ? t.a[0] = 256;
? ? t.a[1] = 255;
? ? t.a[2] = 0x81;
? ? t.a[3] = 2;
? ??
? ? printf("%d",t.b);
return 0;
}
首先256用int存儲(chǔ),所以a[0]只能取其后面一個(gè)字節(jié),為0
最終a的前兩個(gè)字節(jié)的內(nèi)存分布是:
ff00
取其補(bǔ)碼為-256
總結(jié)
- 上一篇: word rectangle
- 下一篇: extent static const