|
希望对需要的人有用,自己收藏~~
结构体、联合体的应用,以及字节对齐和字节序的问题
通讯中,用过的非常多。给你一个我的例子
typedef union
{
FLOAT32 fVal;
INT32 dig;
INT32 iVal;
struct{
FLOAT32 x;
FLOAT32 y;
}complex;
FLOAT64 dfVal;
PROT_TIME time;
}PROTEVENT_VALTYPE; //不同类型的数值
typedef struct
{
struct
{
UINT16 paraType;
UINT8 valType;
UINT8 widthVal;
PROTEVENT_VALTYPE val;
UINT16 paraGroup;
UINT8 phs;
UINT8 lenName;
}head;
UINT8 name[VAR_COMM_SIZE];
}PROTMSG_EVENT_PAR;
对于那种一个整数和几个字节取值的问题,建议不要用结构联合来实现。如:
union bits32
{
int num;
struct
{
char c1;
char c2;
char c3;
char c4;
}byte;
};
这个在不同的CPU架构变现不相同,就是CPU的高低次序问题。在普通的PC即x86cpu上,是小头在前,即c1对应的num的第一个字节,但是在其它一些如PowerPC、sun的SPARC架构CPU上,是大头在前,c1就对应num的第4个字节。
在网络传输中,对这个问题很敏感,就是发生的字节次序问题。在TCP/IP中,规定是网络次序,具体参考一下TCP/IP的数据。里面有不少网络次序数据和本机数据的转换问题。
为了避免这种问题,我们一般在通信中,采用的是移位操作。如
/*****整数和单字节数转换操作,通过移位避开次序问题*****/
#define BYTE0(intval) ( (UINT8)( 0x000000ff&(intval)) )
#define BYTE1(intval) ( (UINT8)(( 0x0000ff00&(intval))>>8) )
#define BYTE2(intval) ( (UINT8)(( 0x00ff0000&(intval))>>16) )
#define BYTE3(intval) ( (UINT8)((0x0ff000000&(intval))>>24) )
/*******************字节组合定义*******************/
#define UINT16COMB(b1,b0) ( (UINT16)(b0) | (((UINT16)(b1))<<8) )
#define INT16COMB(b1,b0) UINT16COMB(b1,b0)
#define UINT32COMB(b3,b2,b1,b0) /
( (UINT32)(b0) /
| (((UINT32)(b1))<<8) /
| (((UINT32)(b2))<<16) /
| (((UINT32)(b3))<<24) )
#define INT32COMB(b3,b2,b1,b0) UINT32COMB(b3,b2,b1,b0)
使用时,可以用:
c1=BYTE0(num);
c2=BYTE1(num);
...
num=UINT32COMB(c3,c2,c1,c0);
实际上移位操作,对于CPU来说,基本上是一个指令周期,比你直接用struct和union还要快。这个问题涉及到32位CPU的整字对齐和整字操作处理问题和CPU的指令优化,具体可以去参考CPU指令的书籍。
对齐规则由编译选项决定的,一般编译器采用缺省的编译选项。一般存储单元按照CPU的字长对齐,对于目前32位主流系统,基本的数据类型char、short、int、float,对齐在整字的开始。
如struct
{
char c;
int i;
float f;
};
c占用第一个字长的第一个字节,而后面的3个字节变长存储空洞;i和f各占1个字长。
struct
{
char c;
char c1;
int i;
float f;
};
这种情况下,c1将分配在c之后,占一个字节,而c1后面就留出来2各空洞。
所以在组织struct或者class时,注意一下成员分布的合理,综合一下存储分配情况。但是从CPU的指令操作上看,CPU一般按照一个字长来执行,操作一个int数要比一个char效率高。也就说说,当CPU读取一个char数时,CPU先从内存中读取一整个字长值到寄存器中,然后将相应char所在的那个字节提取出来,从而完成一个char的取值。
另外:编程时千万注意float *pFVal;指针的使用,浮点数指针一定要指向一个整字起始的内存位置,如上面的&c1地址,否则在一些特定的CPU或单片机中,对非对齐的浮点指针操作,会发生崩溃问题,这个和浮点指令的兼容性问题。典型的是在sun的sparc、POWERPC的一些cpu上就会发生崩溃问题。
想改变编译器的对齐规则,可以在代码中加入:
#pragma pack(push, 1)
.....//代码
#pragma pack(pop)
自:blog.csdn.net/ljhnew/article/details/5829821 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|