通常计算机中的数据存放在存储器或寄存器中.而寄存器的位数便可放映机器字长.一般机器字长可取字节的1,2,4,8倍,这样便于字符处理.在大/中型机器中字长为32位和64位.在微型计算机中字长从4位/8位逐渐发展到目前的32位/64位.
由于不同的及其数据字长不同,每台机器处理的数据字长也不统一,例如奔腾处理器可处理8(字节) / 16(字) / 32(双字) / 64 (四字) ; PowerPC可处理 8(字节) / 16(半字) / 32(字) / 64(双字) . 因此,为了便于硬件实现,通常要求多字节的数据在存储器的存放方式能满足"边界对准"的要求.
下图位存储字长位32位的存储器,可按字节,半字,字,双字访问.在对准边界的32位字长的计算机中,半字地址是2的整数倍,字地址是4的整数倍,双子地址是8的整数倍.当锁存数据不能满足此要求时,可填充一个至多个空白字节.现贴出例子详解.
字(0) | |||
字(4) | |||
字节(11) | 字节(10) | 字节(9) | 字节(8) |
字节(15) | 字节(14) | 字节(13) | 字节(12) |
半字(18) | 半字(16) | ||
半字(22) | 半字(20) | ||
双字(24) | |||
双字 | |||
双字(32) | |||
双字 | |||
双字(40) |
#include<stdio.h>
struct A
{
int a;
char b;
double d;
};
struct B
{
int a;
char b;
char c;
double d;
};
struct C
{
int a;
char b;
char c;
char d;
char e;
double f;
};
struct D
{
int a;
char b;
double c;
char d;
};
int main()
{
printf("%d\n",sizeof(struct A));
printf("%d\n",sizeof(struct B));
printf("%d\n",sizeof(struct C));
printf("%d\n",sizeof(struct D));
}
结果是(测试环境linux gcc) :
16
16
16
24
A=16的情况:int刚好占满一个字 即4个字节. 而char类型则占1个字节,根据上述表格第3行所示,得填充3个字节以满足边界对准要求,此时sizeof(struct A)=4(int)+1(char)+3(空)+8(double)=16.
B也等于16的原因可以和C一起来看,因为char b之后还空着3个字节, char c 和char d 刚好可以填充,不过得是连续的不满足4个字节的数据类型才可以,这也就是为什么D的长度会是24的原因了. 接下来计算下下面例子的B的长度:
还有就是一个结构体的长度要等于结构体里长度最长的成员的整数倍 比如下面的结构体C和D
struct A
{
char a;
char b;
}
struct B
{
int a;
char b;
struct A c;
char d;
double e;
char f;
};
struct C
{
int a;
char b;
struct A c;
char d;
int e;
char f;
};
struct D
{
char a;
int b;
};
struct E
{
int a;
double b;
}
最后还有一个大端,小端的问题(在union中就能体现出来,先测试?多找几台机子才行)
大端: 根据上图的表格,存储器地址低地址在左,则大端模式下,保存一个数据 比如 6 (00000110) 的方式 就是 01100000 也就是说高位存在低地址上.
小端:与大端相反,低地址存低位.