大端和小端
Endian表示数据在存储器中的存放顺序。
如果将一个32位的整数0x12345678存放到一个整型变量(int)中,这个整型变量采用大端或者小端模式在内存中的存储由下表所示。
地址偏移
|
大端模式
|
小端模式
|
0x00
|
12(OP0)
|
78(OP3)
|
0x01
|
34(OP1)
|
56(OP2)
|
0x02
|
56(OP2)
|
34(OP1)
|
0x03
|
78(OP3)
|
12(OP0) |
由上表所知,采用大小模式对数据进行存放的主要区别在于在存放的字节顺序,大端方式将高位存放在低地址,小端方式将低位存放在低地址。
有的处理器系统采用了小端方式进行数据存放,如Intel的奔腾。有的处理器系统采用了大端方式进行数据存放,如IBM半导体和Freescale的PowerPC处理器。不仅对于处理器,一些外设的设计中也存在着使用大端或者小端进行数据存放的选择。CP/IP也使用big-endian方法 (big-endian方法也叫做网络编码)
判断大端小端:
int main()
{
int i = 1;
char *p = (char *)&i;
if(*p==1)
printf("1");
else
printf("2");
}
联合体union联的存放顺序是所有成员都从低地址开始存放:
int checkCPU( )
{
{
union w{
int a;
char b;
}c;
c.a = 1;
return(c.b ==1);
}
}
位域
所谓“位域”是把一个字节中的二进位划分为几
个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
例如:
struct bs{
unsigned a:4
unsigned :0 /*空域*/
unsigned b:4 /*从下一单元开始存放*/
unsigned c:4
}
在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。
2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。
3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。
struct k{
int a:1
int :2 /*该2位不能使用*/
int b:3
int c:2
};
从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。
位域使用:
main()
{
struct bsi{
unsigned a:1;
unsigned b:3;
unsigned c:4;
}bit,*pbit;
bit.a=1;
bit.b=7;
bit.c=15;
printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b &= 3;
pbit->c |= 1;
printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);
}
输出:
[davy@local Work]$ ./a.out
1,7,15
0,3,15
网宿的一道笔试题目
//假设硬件平台是intel x86(little endian)
typedef unsigned int uint32_t;
void inet_ntoa(uint32_t in)
{
char b[18];
register char *p;
p = (char *)∈
#define UC(b) (((int)b)&0xff)
sprintf(b, "%d.%d.%d.%d\n", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
printf(b);
}
# int main()
{
inet_ntoa(0x12345678);
inet_ntoa(0x87654321);
}
阅读(1568) | 评论(0) | 转发(0) |