1. 程式人生 > >IAR中使用struct強制對齊時的一個問題及解決

IAR中使用struct強制對齊時的一個問題及解決

最近在用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;
}