在嵌入式開發中,經常碰到因端序使用不當導致的錯誤,故決定決定將工作中常見的轉序函數進行梳理,一是為了避免犯同樣的錯誤,二是為了以后方便查詢。本文分為四個部分:1、什么是大小端序;2、大小端序數據相互轉換函數;3、應用場景;4、使用總結。
1、什么是大小端序
大端模式:是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中。
小端模式:是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中。
現在,以一個unsigned int整型數據0x12345678為例,其大端序、小端序的存儲內容如圖所示。
2、大小端序數據相互轉換函數
a)將unsigned char數組轉換成“大端序”整數;
/* * Function: ConverseArrayToBeUI * Description: 將無符號字符數組數據轉換成“大端序”整數 * Parameter: srcArray --[in] 源數組數據 * desBeData --[out] 目標“大端序”整數 * Return 0 成功 * 非0 失敗 * Note: * Other: */ int MULCONVERSE_CALL ConverseArrayToBeUI(unsigned char *srcArray,unsigned int *desBeData) { if (srcArray == NULL_POINT || desBeData == NULL_POINT) { return ERR_NULL_POINT; } *desBeData = (unsigned int)(srcArray[0]<<24) + (unsigned int)(srcArray[1]<<16) + (unsigned int)(srcArray[2]<<8) + (unsigned int)srcArray[3]; return _SUCCESS; }
b)將unsigned char數組轉換成“小端序”整數;
/* * Function: ConverseArrayToLeUI * Description: 將無符號字符數組數據轉換成“小端序”整數 * Parameter: srcArray --[in] 源數組數據 * desLeData --[out] 目標“小端序”整數 * Return 0 成功 * 非0 失敗 * Note: * Other: */ int MULCONVERSE_CALL ConverseArrayToLeUI(unsigned char *srcArray,unsigned int *desLeData) { if (srcArray == NULL_POINT || desLeData == NULL_POINT) { return ERR_NULL_POINT; } *desLeData = (unsigned int)(srcArray[3]<<24) + (unsigned int)(srcArray[2]<<16) + (unsigned int)(srcArray[1]<<8) + (unsigned int)srcArray[0]; return _SUCCESS; }
c)將整數按照“大端序”格式存儲在數組中;
/* * Function: ConverseUItoBeArray * Description: 將無符號整數轉換成“大端序”存儲的無符號字符數組 * Parameter: srcData --[in] 源整數 * desBeArray --[out] 目標“大端序”存儲的數組數據 * Return 0 成功 * 非0 失敗 * Note: * Other: */ int MULCONVERSE_CALL ConverseUItoBeArray(unsigned int srcData,unsigned char *desBeArray) { if (desBeArray == NULL_POINT) { return ERR_NULL_POINT; } desBeArray[0] = (unsigned char)(srcData>>24); desBeArray[1] = (unsigned char)(srcData>>16); desBeArray[2] = (unsigned char)(srcData>>8); desBeArray[3] = (unsigned char)srcData; return _SUCCESS; }
d)將整數按照“小端序”格式存儲在數組中。
/* * Function: ConverseUItoLeArray * Description: 將無符號整數轉換成“小端序”存儲的無符號字符數組 * Parameter: srcData --[in] 源整數 * desLeArray --[out] 目標“小端序”存儲的數組數據 * Return 0 成功 * 非0 失敗 * Note: * Other: */ int MULCONVERSE_CALL ConverseUItoLeArray(unsigned int srcData,unsigned char *desLeArray) { if (desLeArray == NULL_POINT) { return ERR_NULL_POINT; } desLeArray[3] = (unsigned char)(srcData>>24); desLeArray[2] = (unsigned char)(srcData>>16); desLeArray[1] = (unsigned char)(srcData>>8); desLeArray[0] = (unsigned char)srcData; return _SUCCESS; }
3、應用場景
PC(小端序)向芯片(大端序)發送數據
假設PC產生一個整數數值0x00000001,經通信接口(比如串口)向芯片發送數據時,按照一次發一字節的方式傳輸數據,那么此時芯片就會收到4字節數據,其內容按照地址從低到高排序為0x01,0x00,0x00,0x00,那么芯片就會認為自己收到的整數數值為0x01000000。
此時,兩個硬件平台就會因為大小端的不同造成數據收發錯誤,此時解決的方法有兩種:1、PC發送數據之前,通過轉換函數ConverseUItoBeArray,將整數數值0x00000001轉換成[00,00,00,01]字符數組,然后經通信接口發給芯片;2、芯片接收到4字節數據之后,通過函數ConverseArrayToLeUI,將[01,00,00,00]轉換成整數0x00000001。
4、使用總結
(1)不同的硬件平台如果采用同一種類型的端序,計算/使用時無需轉序;
(2)不同的硬件平台如果采用不同類型的的端序,但傳輸的字符數組“無需”轉換成多字節基本類型數據(如int,double,float)時,計算/使用時無需轉序;
(3)不同的硬件平台如果采用不同類型的的端序,但傳輸的字符數組“需要”轉換成多字節基本類型數據(如int,double,float)時,計算/使用時需要轉序;