分享一篇關於 C# 高低字節轉換的問題

本篇內容主要講一講高低字節轉換問題;

1、int16 高低位轉換

1.1 Uint16轉成byte數組,高位在前,低位在後

            byte[] command = new byte[2];
            double test1 = 5614;
            UInt16 result = (UInt16)(test1);
            command[0] = (byte)(result >> 8);//高位
            command[1] = (byte)(result & 0xff);//低位
            Console.WriteLine("{0}", FormatBytes(command) );  

結果如下:

1.2 將byte數組(長度2,高字節在前,低字節在後),轉成double數據;

  //==============2==================
            byte[] command2 = new byte[2] { 0x15, 0xee };
            double result2 = command2[0] * 256 + command2[1];
            Console.WriteLine("{0}", result2);

結果如下:

 2、INT32 高低位轉換問題

 2.1將int32 轉成byte數組,要求高字節在前,低字節在後;

        /// <summary>
        /// 將x轉換成通訊用的字節
        /// </summary>
        /// <returns></returns>
        public static byte[] Double_Bytes(double x)
        {
            byte[] byteLL = new byte[4];
            byte[] byteLL2 = new byte[4];
            int Result = (int)(x * 1048576.0);//這個看實際需求
            byteLL2 = BitConverter.GetBytes(Result);
            byteLL[0] = byteLL2[3];
            byteLL[1] = byteLL2[2];
            byteLL[2] = byteLL2[1];
            byteLL[3] = byteLL2[0];
            return byteLL;
        }
        /// <summary>
        /// byte數組爲byte數組賦值的函數
        /// obj[objoff + i] = src[i];
        /// </summary>
        /// <param name="src">源值</param>
        /// <param name="obj">目標數組</param>
        /// <param name="objoff">源數組在目標數組中的偏移</param>
        public static void Eva2bytes(byte[] src, byte[] obj, int objoff)
        {
            for (int i = 0; i < src.Length; i++)
            {
                obj[objoff + i] = src[i];
            }
        }
      //==============3===============
            byte[] command = new byte[4];
            double test1 = 113.2535;
            byte[] byte1 = Double_Bytes(test1);
            Eva2bytes(byte1, command, 0);
            Console.WriteLine(FormatBytes(command));

結果如下:

 

  2.2 將byte數組 (長度2,高字節在前,低字節在後)轉成double;

 public static int ToInt32(byte[] value, int startIndex)
        {
            byte[] dst = new byte[4];
            Buffer.BlockCopy(value, startIndex, dst, 0, 4);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(dst);
            }
            return BitConverter.ToInt32(dst, 0);
        } 

      //==============4==================
            byte[] command4 = new byte[4] { 0x07, 0x14,0x0E,0x56 };
            double result = ToInt32(command4, 0) / 1048576.0;
            Console.WriteLine("{0}", result);

結果如下:

常用單片機內存一個地址只能存八位二進制數,最大數據只能是255(十進制). 
  當需要儲存大於255的數據時,就需要用兩個以上的內存地址,低位字節中的數是原數,高位字節中的數要乘以位數再與低位字節中的數相加纔是你真要的數. 

以下這段摘錄網上的,希望你們看的懂吧

大端模式與小端模式
一、概念及詳解
  在各種體系的計算機中通常採用的字節存儲機制主要有兩種: big-endian和little-endian,即大端模式和小端模式。
  先回顧兩個關鍵詞,MSB和LSB:
  MSB:Most Significant Bit ------- 最高有效位
        LSB:Least Significant Bit ------- 最低有效位
  大端模式(big-edian)
  big-endian:MSB存放在最低端的地址上。
      舉例,雙字節數0x1234 以big-endian的方式存在起始地址0x00002000中:
          | data |<-- address
          | 0x12 |<-- 0x00002000
          | 0x34 |<-- 0x00002001
  在Big-Endian中,對於bit序列中的序號編排方式如下(以雙字節數0x8B8A爲例):
        bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
        ------MSB----------------------------------LSB
        val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
        +--------------------------------------------+
        = 0x8 B 8 A
  小端模式(little-endian)
  little-endian:LSB存放在最低端的地址上。
    舉例,雙字節數0x1234 以little-endian的方式存在起始地址0x00002000中:
    | data |<-- address
          | 0x34 |<-- 0x00002000
          | 0x12 |<-- 0x00002001
  在Little-Endian中,對於bit序列中的序號編排和Big-Endian剛好相反,其方式如下(以雙字節數0x8B8A爲例):
bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
        ------MSB-----------------------------------LSB
        val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
        +---------------------------------------------+
        = 0x8 B 8 A 

二、數組在大端小端情況下的存儲:
  以unsigned int value = 0x12345678爲例,分別看看在兩種字節序下其存儲情況,我們可以用unsigned char buf[4]來表示value:
  Big-Endian: 低地址存放高位,如下:
       高地址
        ---------------
        buf[3] (0x78) -- 低位
        buf[2] (0x56)
        buf[1] (0x34)
        buf[0] (0x12) -- 高位
        ---------------
        低地址
Little-Endian: 低地址存放低位,如下:
        高地址
        ---------------
        buf[3] (0x12) -- 高位
        buf[2] (0x34)
        buf[1] (0x56)
        buf[0] (0x78) -- 低位
        --------------
        低地址

  三、大端小端轉換方法:
  Big-Endian轉換成Little-Endian如下:
#define BigtoLittle16(A)                 ((((uint16)(A) & 0xff00) >> 8) | \
                                                          (((uint16)(A) & 0x00ff) << 8))
#define BigtoLittle32(A)                 ((((uint32)(A) & 0xff000000) >> 24) | \
                                                          (((uint32)(A) & 0x00ff0000) >> 8) | \
                                                          (((uint32)(A) & 0x0000ff00) << 8) | \
                                                          (((uint32)(A) & 0x000000ff) << 24))

  四、大端小端檢測方法:
  如何檢查處理器是big-endian還是little-endian?
  聯合體union的存放順序是所有成員都從低地址開始存放,利用該特性就可以輕鬆地獲得了CPU對內存採用Little-endian還是Big-endian模式讀寫。

int checkCPUendian()
{
union{ unsigned
int a; unsigned char b; }c; c.a = 1; return (c.b == 1); }
 

好久沒有寫博客了,今天遇到了一個比較愚蠢的問題,必須記錄一下,引以爲戒了;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章