首页 新闻 搜索 专区 学院

总看到些位移的代码,不懂为什么要这么写!效率吗?

0
悬赏园豆:60 [已解决问题] 解决于 2013-12-22 16:05

总看到些位移的代码,不懂为什么要这么写!

        public static byte[] GetBytes(long value) 
        {
            byte b0 = (byte)((value >> 56) & 0xFF);
            byte b1 = (byte)((value >> 48) & 0xFF);
            byte b2 = (byte)((value >> 40) & 0xFF);
            byte b3 = (byte)((value >> 32) & 0xFF);
            byte b4 = (byte)((value >> 24) & 0xFF);
            byte b5 = (byte)((value >> 16) & 0xFF);
            byte b6 = (byte)((value >> 8) & 0xFF);
            byte b7 = (byte)((value >> 0) & 0xFF);

            byte[] bytes = new byte[9];
            bytes[1] = b0;
            bytes[2] = b1;
            bytes[3] = b2;
            bytes[4] = b3;
            bytes[5] = b4;
            bytes[6] = b5;
            bytes[7] = b6;
            bytes[8] = b7;

            return bytes;   
        }

1、这样的写法和Encoding的GetBytes能相比吗?这样写有什么优势?

2、为什么是这样写。(byte)((value >> 0) & 0xFF),步长是8

3、0xff写16进制与直接写十进制有什么差别呢?十进制可读性不是更高吗?

4、有没有什么好资料能让我很容易明白&、|、>>、<<等操作符在什么场合下使用会有效率提高

滴答的雨的主页 滴答的雨 | 老鸟四级 | 园豆:3690
提问于:2013-12-19 15:02
< >
分享
最佳答案
1

1、首先 Encoding 的 GetBytes 是将字符串类型转换成指定编码的字节数组,不会接收 long 类型的数据,所以同你给出的 GetBytes 方法是有功能上的区别的。因此就谈不上什么比较优势。

2、这个你得问写此方法的人,他写的此方法的用途是什么。

3、没有差别,可读性是针对不同的人来说的,从 C/C++转过来的程序员更喜欢读 16 进制。

4、这很多,我只能举一个除法实现方法的例子:http://blog.csdn.net/imcdragon/article/details/6850530

收获园豆:35
Launcher | 高人七级 |园豆:45045 | 2013-12-19 15:26

想这样转化为byte,不管怎样左宜右宜,只要将我真实数据的byte都保存,再反解析的时候再根据规则解析出来就行了?所以我觉得Encoding的GetBytes和问题所列代码段,原理是一样的。。。

滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-19 17:10

@滴答的雨(何雨泉): 你要认为原理一样,我也没办法。虽然我觉得程序员不应该这么不严谨。

Launcher | 园豆:45045 (高人七级) | 2013-12-19 17:18

@Launcher: ……没,我只是觉得一样,我不大了解。感觉是转换和解析过程。只是内部处理的字节数目不一样的,比如long是8bytes,int是4bytes

滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-19 17:22

@滴答的雨(何雨泉): 所以我就觉得这个函数很蹊跷,因为 long 也是 4 byte。

 

请看一下 Encoding 的 GetBytes 方法(http://msdn.microsoft.com/en-us/library/system.text.encoding.getbytes(v=vs.110).aspx),没有重载的参数是 long 类型的。如果原理都一样,那 BitConvert(http://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx) 不就多余了吗?一个是编码,是将一种编码形式的字符串转换成另一种编码的字节数组(注意了,这里的参数是字符串,不是值类型数据,string str="1" 同 int n = 1 是一样的吗?),一个是转换成等价的字节数组(也就是值类型在内存中的等价表现形式)。

 

Launcher | 园豆:45045 (高人七级) | 2013-12-19 18:08

@Launcher: 其实我纠结的是这个,long这里能转换成等价的字节数组。。这时在内存中是以值类型存在的吗?如果这样的话,这个就比较帅了。。。

其实我想表达的原理一样是,他们可以认为是都经过左宜右宜就变成字节数组了。最主要的是如果long像上面这样转换后还是值类型,这个要怎么理解?

滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-19 21:38

@滴答的雨(何雨泉): 首先 long 本身就是值类型,数据类型是相对于编程语言的,跟数据类型在内存中的存储方式无关,编译器会决定某种数据类型的数据如何存储在内存中,内存中数据的最小存储单位是字节(BYTE)。其次,我没有一句话有说或者暗示“long像上面这样转换后还是值类型”。最后,我确实不太明白你想知道什么,因为从你的话里看出你缺乏基本的计算机理论知识,因此我建议你读读《计算机组成和原理》、《操作系统》、《编译原理》。

 

Launcher | 园豆:45045 (高人七级) | 2013-12-20 09:24

@Launcher: 

1、谢谢你的建议,计算机理论基础知识真的很差。我还有个问题

2、BitConvert中没有decimal的类型,若要把这东西转换为byte[]要怎么做呢?(BitConvert不开出此重载是基于什么考虑的呢?)

滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 10:09

@滴答的雨(何雨泉): 还是看 MSDN,http://msdn.microsoft.com/en-us/library/system.bitconverter(v=vs.110).aspx,此链接我已经在上面给出过了。decimal 是 struct ,不是基础数据类型(http://msdn.microsoft.com/zh-cn/library/system.decimal(v=vs.110).aspx)。Decimal.GetBits 可以得到 int[4]。

Launcher | 园豆:45045 (高人七级) | 2013-12-20 10:29

@Launcher: 非常感谢,我再看看

滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 12:04
其他回答(2)
0

这个代码

bytes[0]哪去了?

(value >> 8)  & 0xFF),先向右移动8位(其实就是去掉最后8位),再和11111111做“与”运算,这样,除了最后8位之外其它位都会是0。

这里边的内容基本就和BitConvert.GetBytes方法没什么区别,只是BitConvert.GetBytes转换出来的是低位在前高位在后,这个是高位在前低位在后

收获园豆:20
vbfool | 园豆:176 (初学一级) | 2013-12-19 15:31

非常感谢,这周末得好好补习下二进制的知识了。基本都忘记了。对于这些操作符也不熟,所以很多算法都没办法进行查看。。。

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-19 17:11

我看了下现在bitConvert中的代码是

public static unsafe byte[] GetBytes(long value)
{
    byte[] buffer = new byte[8];
    fixed (byte* numRef = buffer)
    {
        *((long*) numRef) = value;
    }
    return buffer;
}

它是直接用地址的。和上面代码不大一样哎

 

 

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 09:52

@滴答的雨(何雨泉): .NET的基础类型基本都是直接用地址的,因为它要保证效率。一般使用的时候,我都是用的GetBytes()之后再Reverse()来实现上边代码的功能。

毕竟unsafe不是什么地方都能用的,比如WP上就不能用

支持(0) 反对(0) vbfool | 园豆:176 (初学一级) | 2013-12-20 10:01

@vbfool: 一定要弄成高位在前吗?高位在前是行业规范吗?高位在前就能通用?(哎,我是小白)比如在wp中不能使用unsafe代码,GetBytes里面的unsafe就直接不能用了吧?还怎么先GetBytes再Reverse

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 10:24

@滴答的雨(何雨泉): Windows(也有部分其它系统)的默认是低位在前高位在后,而其它部分架构系统,有的是高位在前低位在后的,这两种都算是行业规范,做文件解析和内存分析的时候,要十分注意这点

支持(0) 反对(0) vbfool | 园豆:176 (初学一级) | 2013-12-20 10:32

@vbfool: 

我写了份代码,想试试左移右移和bitConvert是否是相反的,但是结果是这样的

代码:

            int num = 10000;
            byte[] bytes1 = IntToBytes(num);
            byte[] bytes2 = BitConverter.GetBytes(num);

        private byte[] IntToBytes(int value)
        {
            byte[] bytes = new byte[4];
            bytes[0] = (Byte)(value >> 0);
            bytes[1] = (Byte)(value >> 8);
            bytes[2] = (Byte)(value >> 16);
            bytes[3] = (Byte)(value >> 32);

            return bytes;
        }

结果:

1、IntToBytes结果: 16  39  0  16

2、BitConverter结果: 16  39  0  0

 

 

 

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 12:03

@滴答的雨(何雨泉): BitConvert好像可以设置高低位顺序的,看看它的文档

支持(0) 反对(0) c99 | 园豆:1864 (小虾三级) | 2013-12-20 13:07

@滴答的雨(何雨泉): 

 bytes[3] = (Byte)(value >> 32);

应该是

 bytes[3] = (Byte)(value >> 24);

支持(0) 反对(0) vbfool | 园豆:176 (初学一级) | 2013-12-20 15:41

@vbfool: 非常感谢。让我周末在嘻嘻回味下

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-20 15:48
0

位运算的CPU消耗相当小,对于运算量很大的计算有好处,比如100%32这个操作,用位运算的表达就是100&(32-1),CPU周期的消耗有10倍差距

收获园豆:5
Domi.Z | 园豆:125 (初学一级) | 2013-12-21 17:11

非常感谢

支持(0) 反对(0) 滴答的雨 | 园豆:3690 (老鸟四级) | 2013-12-22 16:05
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册