很早想說(shuō)說(shuō)這個(gè)問(wèn)題了,經(jīng)常也會(huì)有很多公司拿位域出來(lái)考人,呵呵要真的想弄清楚還要一點(diǎn)點(diǎn)的分析。
這里先看看網(wǎng)宿的一道筆試題目:
//假設(shè)硬件平臺(tái)是intel x86(little endian)
char *inet_ntoa(uint32_t in)
{
static char b[18];
register char *p;
p = (char *)in;
#define UC(b) (((int)b)&0xff)
(void) snprintf(b, sizeof(b),
"%d. %d. %d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
return (b);
}
int main()
{
printf("%s, %s", inet_ntoa(0x12345678), inet_ntoa(87654321));
}
有點(diǎn)難度的一道題目,其實(shí)理解的也很簡(jiǎn)單。
位域分析
位域是c++和c里面都有的一個(gè)概念,但是位域有一點(diǎn)要注意的有很多問(wèn)題我們一樣樣的看:
大端和小端字節(jié)序
這個(gè)很簡(jiǎn)單,就是起始點(diǎn)該怎么確定。
先看一個(gè)程序:
union {
struct
{
unsigned char a1:2;
unsigned char a2:3;
unsigned char a3:3;
}x;
unsigned char b;
}d;
int main(int argc, char* argv[])
{
d.b = 100;
return 0;
}
那么x的a1,a2,a3該怎么分配值,100的二進(jìn)制是:0110 0100,那么a1到a3是不是就是依次取值恩?
不是!
我們先看看100分配位的低端是左邊的0還是右邊的0?很明顯是右邊的0,那么我們?cè)倏碼1到a3的分配是從低端到高端的
那么,對(duì)應(yīng)的應(yīng)該是
<<<<<<--內(nèi)存增大
a3 a2 a1
011 001 00
內(nèi)存增大之所以這么寫(xiě)是因?yàn)椋?11是在高位!
而不是通常認(rèn)為的的:
a1 a2 a3
011 001 00
還有一個(gè)情況多見(jiàn)就是一個(gè)二進(jìn)制的數(shù)字轉(zhuǎn)化為點(diǎn)分十進(jìn)制數(shù)值,如何進(jìn)行,這里涉及到大端還是小端的問(wèn)題,上面沒(méi)有涉及,主要是因?yàn)樯厦媸且粋€(gè)字節(jié),沒(méi)有這個(gè)問(wèn)題,多個(gè)字節(jié)就有大端和小端的問(wèn)題了,如下:
int main(int argc, char* argv[])
{
int a = 0x12345678;
char *p = (char *)&a;
char str[20];
sprintf(str,"%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
printf(str);
return 0;
}
這個(gè)程序假設(shè)是小端字節(jié)序,那么結(jié)果是什么?
我們看看應(yīng)該怎么放置呢?
每個(gè)字節(jié)8位,0x12345678分成4個(gè)字節(jié),就是從高位字節(jié)到低位字節(jié):12,34,56,78,那么這里該怎么放?如下:
---->>>>>>內(nèi)存增大
78 56 34 12
因?yàn)檫@個(gè)是小端,那么小內(nèi)存對(duì)應(yīng)低位字節(jié),就是上面的結(jié)構(gòu)。