.Net冷知識之UInt32轉換為Byte的方法1、2、3


老天爺你算是贏了,忽冷忽熱的搞毛啊。最近因為各種原因掌握了豐富的就診經驗(好吧,和這篇博文一樣毫無意義的技能Get★daze)。

本來這篇博文的內容是上周沖澡的時候腦洞大開的成果,結果由於各(lan)種(de)原(dong)因(shou)拖延到了今天,那就順手當作三八婦女節獻禮好了(<ゝω・)綺羅星☆。

今天要討論的是有多少種無趣的手段把一個UInt32拆成4個Byte。至於其他長度整形的拆解就請自行舉一反三吧。

首先,肯定是第一個想到的,就是進行位運算。沒什么好說的,關門放代碼:

byte p1=(byte)(ipt >> 24);
byte p2=(byte)(ipt >> 16);
byte p3=(byte)(ipt >> 8);
byte p4=(byte)(ipt);

上述代碼通過位移分別從高到低取得4個byte,簡單實用。通常這種方法就完全夠用了(唯一的問題就是需要口算位移……好煩)。但是標題都劇透了1、2、3,這時候放棄博文就結束了。那么,乘我還沒被凍死就進入方法2吧。

方法2的想法倒是很直接:既然一個UInt32在內存中分配了4個字節的長度,為何我們不直接訪問這4個字節呢?就像吐司面包一樣,直接平分4片就是了。

為了平分一個UInt32,就要直接操作內存。C#中除了幾個特殊的地方,平常沒有人需要用到指針這玩意。不過既然玩的就是腦洞打開,還是果斷祭出許久沒見到的指針吧:

byte* p = (byte*)&ipt;
byte p1=p[3];
byte p2=p[2];
byte p3=p[1];
byte p4=p[0];

由於X86平台上采用的是Little Ending布局,所以這里內存訪問的順序是和直覺相反的(好吧,其實內存布局問題早忘了,要不是看到結果反了也不會順手查了下WIKI)。小細節不要那么在意啦,還是速度說下下一種吧。

方法3其實應該算是方法2的變種。既然用指針能訪問每個byte,那除了指針外還有什么方法也能達到同樣效果呢?

C里面有個叫共用體(union)的特殊類型,此類型的神奇效果是其字段共用一個內存位置,也就是說一個UInt32在內存中是可以和4個Byte重疊在一起的。如果我們可以用這種方法的話,不就意味着可以直接讀到分割的結果了么?那么,唯一的問題是共用體在C#中沒見過啊?沒有一個類型叫union的玩意?

其實,這玩意是存在的。只是除了P/Invoke調用以外實在太無存在干了。其實就是通過StructLayoutAttribute指定手動內存布局,並通過FieldOffsetAttribute手動將內存布局重疊到一起。代碼如下:

[StructLayout(LayoutKind.Explicit)]
internal struct UIntByteConverter
{
    [FieldOffset(0)]
    public uint Source;

    [FieldOffset(0)]
    public byte part4;

    [FieldOffset(1)]
    public byte part3;

    [FieldOffset(2)]
    public byte part2;

    [FieldOffset(3)]
    public byte part1;
}

然后接下來的事情就簡單了,也就是對Source賦值完直接讀取結果罷了。

那么,本篇博文就這么結束了。有沒有覺得什么東西怪怪的?

有么?

沒有么?

有么?

這是湊字數么?

這不是湊字數么?

……

……

……

……

好吧,其實從標題開始我就沒說過只有三種方法嘛。至少還有種方法我是見別人有這么用過(不過對一個不太水的程序員來說,應該是毫無意義的方法來着)。

方法0(對,我就是喜歡從零數起,你咬我啊):轉成字符串然后拆分字符串再轉回來。

一看就知道效率很低,而且其實寫起來也很麻煩……

var temp=ipt.ToString("X8");
byte p1=byte.Parse(temp.Substring(0, 2), NumberStyles.HexNumber);
byte p2=byte.Parse(temp.Substring(2, 2), NumberStyles.HexNumber);
byte p3=byte.Parse(temp.Substring(4, 2), NumberStyles.HexNumber);
byte p4=byte.Parse(temp.Substring(6, 2), NumberStyles.HexNumber);

那么,以上方法的效率如何呢?說實話除了方法3要多一個對象創建而方法0完全坑爹外差別好小。對一個沒停葯的人來說方法1完全夠了(不過我總覺得某些方面方法3也有奇效)。具體如何請自行下載代碼自行跑測試吧。

代碼點我下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM