下面这样的一个结构体:
struct stu1
{
int i;
char c;
int j;
};
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成
员的偏移量加上最后一个成员的大
小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个
成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 二、结构体大小必须是所有成员大小的整数倍,也就是必须为最占内存成员数据类型大小的整数倍;
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
如下结构体定义:
typedef struct tagItemData
{
unsigned char uNo;【1】
unsigned char uConnectState; //uConnectState = 1 means connect targe board other else【2】
unsigned char downMod; //0x00 == ETH 0x01 == RS530 0x02 == E1【3】
unsigned char uEthRateMod; //0x00 = 10M/ 0x01 = 100M 【4】
//wo do not mind the data stream
unsigned char uClkSel[2];【6】
unsigned char uRateData[2];【8】
unsigned char uRateNo[2]; 【10】
unsigned char szExtClk[2][10];【30】
unsigned short uDelayTime[2];【34+2=36%sizeof(long)==0】
long lThreshHold[2]; //do not down perr actually【44】
unsigned char uBrustMod[2];【46】
unsigned char uBrustLen[2];【48】
unsigned char uIntTime[2];// channel Int Time UNIT is 10s
//add additional items for test
char uBer[2][3];【54】
unsigned char uEdge[2];【56+4=60%4=0】//总体内存必须保证为最大数据类型所占内存的N倍;(N为正整数);
}ITEMDATA,*PITEMDATA;
可以得出sizeof(ITEMDATA)=60;
验证结构体关于字对齐的存储方式:
方法:将结构体内容完全复制到堆中,将堆中数据一一输出;
代码如下:
#include"stdio.h"
#include"stdlib.h"
#include"memory.h"
typedef struct tagTest
{
char a;
char b;
int c;
}TEST,*PTEST;//由于字对齐,所占内存为8BYTES;
void main()
{
TEST _test={0x01,0x02,0x01020304};
PTEST _ptest=(PTEST)(&_test);
void* _pvoid;
_pvoid=malloc(sizeof(TEST));
memset(_pvoid,0x00,sizeof(TEST));
memcpy((void*)_pvoid,(void*)_ptest,sizeof(TEST));
char* _pchar=(char*)_pvoid;
for(int i=0;i<sizeof(TEST);i++)
printf("%d\n",*(_pchar+i));
}
输出结果:
1
1
-52
-52
4
3
2
1
press anykey to continue
两个-52即为为满足字对齐条件而补齐在char b;后的2个空字节;