.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也有奇效)。具体如何请自行下载代码自行跑测试吧。

代码点我下载

你可能感兴趣的:(.net)