字节序及其实现方法
一、字节序
我们一般把字节(byte)看作是数据的最小单位。当然,其实一个字节中还包含8个比特(bit)。字节序主要体现在字节之间的顺序,与位无关。
大端字节序 Big Endian(常见的有Motorola)
而所谓大字节序(big endian),便是指其“最高有效位(most significant byte)”落在低地址上的存储方式。例如像地址a写入0x0A0B0C0D之后,在内存中的数据便是:
小端字节序 Little Endian(常见的有Intel)
而对于小字节序(little endian)来说就正好相反了,它把“最低有效位(least significant byte)”放在低地址上。例如:
二、实现方法(C#)
public static int GetSignalValueInBits(byte[] MsgArray,int byteNumber, int BitNum,int Length,string ByteOrder)
{
int nSigValueInBits = 0;
if (Length != 0 && MsgArray != null)
{
int nBytesToRead = 0;
/* 计算信号所包括的字节数 */
nBytesToRead = nGetNoOfBytesToRead(BitNum, Length);
/* 无论是哪种字节序,字节内顺序相同 */
int CurrBitNum = BitNum;
/* 若字节序是Motorola,则应该反向读取字节 */
int nByteOrder = (ByteOrder == "Intel(Litter Endian)") ? 1 : -1;
bool bValid = bValidateSignal(MsgArray.Count(), byteNumber, BitNum, Length, nByteOrder);
if (bValid == true)
{
int nBitsRead = 0;
for (int i = 0; i < nBytesToRead; i++)
{
/* 在消息字节数组中取字节的位置是byteNumber - 1 */
byte byMsgByteVal = MsgArray[(byteNumber - 1) + (nByteOrder * i)];
if (CurrBitNum != 0)
{
byMsgByteVal >>= CurrBitNum;
}
/* 计算当前字节中读取多少bits */
int nCurrBitsToRead = Math.Min(8 - CurrBitNum, Length - nBitsRead);
/*读取完第一个字节,下一个字节总是从第一个bit开始,所以从置 CurrBitNum */
CurrBitNum = 0;
byte byMask = 0;
byMask = (byte)(Math.Pow((float)2.0, (int)nCurrBitsToRead) - 1);
//更新信号值
nSigValueInBits |= (int)(byMsgByteVal & byMask) << nBitsRead;
nBitsRead += nCurrBitsToRead;
}
}
}
return nSigValueInBits;
}
//计算需要读取的字节数
private static int nGetNoOfBytesToRead(int nBitNum, int nSigLen)
{
int nBytesToRead = 1; //第一个字节
int nRemainingLength = nSigLen - (8 - nBitNum);
if (nRemainingLength > 0)
{
// 计算总共包含的字节数
nBytesToRead += (int)(nRemainingLength / 8);
// 计算跨越到下一个字节的bit数.
int nTotalBitsConsidered = ((nBytesToRead - 1) * 8) + (8 - nBitNum);
if (nTotalBitsConsidered < (int)nSigLen)
{
nBytesToRead++;
}
}
return nBytesToRead;
}
//判断信号长度是否超过了消息数组
private static bool bValidateSignal(int nDLC, int nByteNum, int nBitNum, int nLength, int bDataFormat)
{
bool bValid = true;
int nBytesToRead = nGetNoOfBytesToRead(nBitNum, nLength);
bValid = (bDataFormat == 1) ? (int)(nByteNum + nBytesToRead - 1) <= nDLC : (int)(nByteNum - nBytesToRead) >= 0;
return bValid;
}
public static int bytesToInt(byte[] src)
{
int value;
value = (int)(((src[0] << 8) & 0xFF00)
| (src[1] & 0xFF));
return value;
}