IAR中使用struct強制對齊時的一個問題及解決
阿新 • • 發佈:2019-01-26
最近在用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;
}