struct msgA_
{
int ix ;
char msg[28] ;
double dx ;
} ;
typedef struct msgA_ msgA ;
struct msgB_
{
int iy ;
char msg[28] ;
char type[10] ;
} ;
typedef struct msgB_ msgB ;
struct msgC_
{
int iz ;
char msg[28] ;
double x[6] ;
} ;
typedef struct msgC_ msgC ;
#define TYPEA 1
#define TYPEB 2
#define TYPEC 3
struct Packet_
{
int PacketType ;
union
{
msgA a ;
msgB b ;
msgC c ;
}Pmsg ;
} ;
typedef struct Packet_ Packet ;
void Test(char* ptr , unsigned int iLen )
{
printf("(%d) for length\n",iLen) ;
Packet* msgptr = (Packet*) ptr ;
switch(msgptr->PacketType)
{
case TYPEA :
printf("type A received \n") ;
break ;
case TYPEB :
printf("type B received \n") ;
printf("(%d)(%s)(%s)\n",msgptr->Pmsg.b.iy,
msgptr->Pmsg.b.msg,msgptr->Pmsg.b.type) ;
break ;
case TYPEC :
printf("type C received \n") ;
printf("(%d)(%s)(%.1f)(%.1f)(%.1f)(%.1f)(%.1f)(%.1f)\n",
msgptr->Pmsg.c.iz , msgptr->Pmsg.c.msg,
msgptr->Pmsg.c.x[0],msgptr->Pmsg.c.x[1],
msgptr->Pmsg.c.x[2],msgptr->Pmsg.c.x[3],
msgptr->Pmsg.c.x[4],msgptr->Pmsg.c.x[5] ) ;
break ;
}
}
int main()
{
Packet p1 ;
p1.PacketType = 3 ;
p1.Pmsg.c.iz = 10000 ;
strcpy(p1.Pmsg.c.msg,"to be the one") ;
p1.Pmsg.c.x[0] = 1.1 ;
p1.Pmsg.c.x[1] = 2000.2 ;
p1.Pmsg.c.x[2] = 3000.3 ;
p1.Pmsg.c.x[3] = 4000.4 ;
p1.Pmsg.c.x[4] = 5000.5 ;
p1.Pmsg.c.x[5] = 6000.6 ;
Test((char*) &p1,sizeof(p1)) ;
printf("=========================\n") ;
Packet p2 ;
p2.PacketType = 2 ;
p2.Pmsg.b.iy = 100 ;
strcpy(p2.Pmsg.b.msg,"hello world") ;
strcpy(p2.Pmsg.b.type,"type type") ;
Test((char*) &p2,sizeof(p2)) ;
}
output :
(88) for length
type C received
(10000)(to be the one)(1.1)(2000.2)(3000.3)(4000.4)(5000.5)(6000.6)
=========================
(88) for length
type B received
(100)(hello world)(type type)
可以看到 , Packet 的變數 sizoeof 一率是 88 , 這是因為 union 中去找到最大的 值 ,
然後不管你是使用 union那一種 structure , 一率配給最高的那個 structure memory !!!!
struct Packet_
{
int PacketType ;
union
{
msgA a ;
msgB b ;
msgC c ;
}Pmsg ;
} ;
這裡面 msgC
struct msgC_
{
int iz ;
char msg[28] ;
double x[6] ;
} ;
佔了 80 bytes 最高 , 所以就是 80 bytes 加上此例中 int PacketType 8 bytes = 88 bytes !!!!!
首先 , msgC 為什麼是 80 bytes ? 4 + 28 + 6*8 = 80 bytes !!!!
那為甚麼 加上 PacketType 是 88 bytes 而不是 84 bytes ? 這是因為 natural alignment ,
double x 一定要配置在 memory alignment 是 8 的倍數的記憶體 , 此例中唯有 PacketType 佔 8 bytes 才做的到 !!!!!
有無發現 msgC x[0] 剛好在 4 + 28 = 32 可以整除 8 , 所以此時的 iz 給 4 bytes 即可 !!!!!
Edit on 2014/01/01 :
struct
s_
{
char
c;
double
d;
int
s;
} structc_t;
Edit2 :
struct Mars_
{
char a ;
double d ;
int i ;
} ;
struct c_
{
char a ;
double d ;
short s ;
char arr[12] ;
};
在 32 bits OS Linux , Intel x86-64 cpu 是得到 : 16 , 28 , 64 bits OS Linux Intel x86-64 得到 24,32 ,
32 bits Linux 的值可以參考 :
http://en.wikipedia.org/wiki/Data_structure_alignment
其中一段話是重點 :
when compiling for 32-bit x86
A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux (8-byte with -malign-double compile time option).
#pragma pack(n) 就是限制對齊 n 而非 struct 最大的 member size
#pragma pack() 是 取消這個語法 !!!
此例中 , 你使用 pack(4) 你就會得到 84 , 如使用 pack(8) , pack(16) 沒有效果 , 因為 大於 structure 最大 size 的 member
就沒有意義了 !!! 要注意的是 pack(4) 讓 double x 不是位在 memory 是 8 倍數上 , 最可能的危險是 :
這個變數可能 4 bytes 在 cache line 1 , 4 bytes 在 cache line 2 , 此時就不能正常地 atomic 處理這樣的變數了 !!!!!
留言列表