最近在用IAR开发MSP430程序过程中发现了一个问题,具体描述是这样的
首先定义了一个struct并强制1个字节对齐
#pragma pack(push) //保存对齐状态
#pragma pack(1)//设定为4字节对齐
typedef struct
{
uint8_t fix_mode;
uint32_t latitude; //纬度 分扩大100000倍,实际要除以100000
uint8_t nshemi; //北纬/南纬,N:北纬;S:南纬
uint32_t longitude; //经度 分扩大100000倍,实际要除以100000
uint8_t ewhemi; //东经/西经,E:东经;W:西经
}GprsLBS;
#pragma pack(pop) //保存对齐状态
然后写了一个函数
u_char StrToNum(u_char *str,char end_char,u_int *num)
{
uint8_t i = 0;
while(str[i] != end_char)
{
if(str[i] <= '9' && str[i] >= '0')
{
(*num) = (*num)*10 + (str[i] - 0x30);
}
else if(str[i] == '.')
{
}
else
{
return 0;
}
i ++;
}
return 1;
}
在调用的时候将结构体中4字节的数据取地址并当参数传入
StrToNum(p,',',&(rxlbs.longitude))
不仅会报告一个警告Warning[Pa039]: use of address of unaligned structure member
运算出来的数据有时也会不对
最后经我调试发现,当&(rxlbs.longitude)的地址是奇数的时候,对其对应参数*num的直接赋值操作会运算到其地址的前一个字节地址,导致结构成员nshemi的值变掉,而运算出来的longitude值也不对,因此,在430中存储结构正常是以偶数地址开始,而人为的定义struct并强制1个字节对齐会导致其成员会出现奇地址的出现,而用奇地址的成员取地址并传参数给函数,函数内部对其的赋值会出错。
解决办法
1,不使用1字节对齐方式
2,如果非要使用,不要对没对齐的struct成员取地址,可以直接赋值
3,非要有上述操作,不能使用将取地址后当参数传入的成员指针直接赋值运算等方式,可以临时建一个变量操作,操作完后将变量的值memcpy到成员的指针。
比如将我上述的函数改成
u_char StrToNum(u_char *str,char end_char,u_int *num)
{
uint8_t i = 0;
uint32_t num_temp = 0;
while(str[i] != end_char)
{
if(str[i] <= '9' && str[i] >= '0')
{
num_temp = num_temp*10 + (str[i] - 0x30);
}
else if(str[i] == '.')
{
}
else
{
return 0;
}
i ++;
}
memcpy(num,&num_temp,sizeof(u_int));
return 1;
}