总看到些位移的代码,不懂为什么要这么写!
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、有没有什么好资料能让我很容易明白&、|、>>、<<等操作符在什么场合下使用会有效率提高
1、首先 Encoding 的 GetBytes 是将字符串类型转换成指定编码的字节数组,不会接收 long 类型的数据,所以同你给出的 GetBytes 方法是有功能上的区别的。因此就谈不上什么比较优势。
2、这个你得问写此方法的人,他写的此方法的用途是什么。
3、没有差别,可读性是针对不同的人来说的,从 C/C++转过来的程序员更喜欢读 16 进制。
4、这很多,我只能举一个除法实现方法的例子:http://blog.csdn.net/imcdragon/article/details/6850530
想这样转化为byte,不管怎样左宜右宜,只要将我真实数据的byte都保存,再反解析的时候再根据规则解析出来就行了?所以我觉得Encoding的GetBytes和问题所列代码段,原理是一样的。。。
@滴答的雨(何雨泉): 你要认为原理一样,我也没办法。虽然我觉得程序员不应该这么不严谨。
@Launcher: ……没,我只是觉得一样,我不大了解。感觉是转换和解析过程。只是内部处理的字节数目不一样的,比如long是8bytes,int是4bytes
@滴答的雨(何雨泉): 所以我就觉得这个函数很蹊跷,因为 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: 其实我纠结的是这个,long这里能转换成等价的字节数组。。这时在内存中是以值类型存在的吗?如果这样的话,这个就比较帅了。。。
其实我想表达的原理一样是,他们可以认为是都经过左宜右宜就变成字节数组了。最主要的是如果long像上面这样转换后还是值类型,这个要怎么理解?
@滴答的雨(何雨泉): 首先 long 本身就是值类型,数据类型是相对于编程语言的,跟数据类型在内存中的存储方式无关,编译器会决定某种数据类型的数据如何存储在内存中,内存中数据的最小存储单位是字节(BYTE)。其次,我没有一句话有说或者暗示“long像上面这样转换后还是值类型”。最后,我确实不太明白你想知道什么,因为从你的话里看出你缺乏基本的计算机理论知识,因此我建议你读读《计算机组成和原理》、《操作系统》、《编译原理》。
@Launcher:
1、谢谢你的建议,计算机理论基础知识真的很差。我还有个问题
2、BitConvert中没有decimal的类型,若要把这东西转换为byte[]要怎么做呢?(BitConvert不开出此重载是基于什么考虑的呢?)
@滴答的雨(何雨泉): 还是看 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: 非常感谢,我再看看
这个代码
bytes[0]哪去了?
(value >> 8) & 0xFF),先向右移动8位(其实就是去掉最后8位),再和11111111做“与”运算,这样,除了最后8位之外其它位都会是0。
这里边的内容基本就和BitConvert.GetBytes方法没什么区别,只是BitConvert.GetBytes转换出来的是低位在前高位在后,这个是高位在前低位在后
非常感谢,这周末得好好补习下二进制的知识了。基本都忘记了。对于这些操作符也不熟,所以很多算法都没办法进行查看。。。
我看了下现在bitConvert中的代码是
public static unsafe byte[] GetBytes(long value) { byte[] buffer = new byte[8]; fixed (byte* numRef = buffer) { *((long*) numRef) = value; } return buffer; }
它是直接用地址的。和上面代码不大一样哎
@滴答的雨(何雨泉): .NET的基础类型基本都是直接用地址的,因为它要保证效率。一般使用的时候,我都是用的GetBytes()之后再Reverse()来实现上边代码的功能。
毕竟unsafe不是什么地方都能用的,比如WP上就不能用
@vbfool: 一定要弄成高位在前吗?高位在前是行业规范吗?高位在前就能通用?(哎,我是小白)比如在wp中不能使用unsafe代码,GetBytes里面的unsafe就直接不能用了吧?还怎么先GetBytes再Reverse
@滴答的雨(何雨泉): Windows(也有部分其它系统)的默认是低位在前高位在后,而其它部分架构系统,有的是高位在前低位在后的,这两种都算是行业规范,做文件解析和内存分析的时候,要十分注意这点
@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
@滴答的雨(何雨泉): BitConvert好像可以设置高低位顺序的,看看它的文档
@滴答的雨(何雨泉):
bytes[3] = (Byte)(value >> 32);
应该是
bytes[3] = (Byte)(value >> 24);
@vbfool: 非常感谢。让我周末在嘻嘻回味下
位运算的CPU消耗相当小,对于运算量很大的计算有好处,比如100%32这个操作,用位运算的表达就是100&(32-1),CPU周期的消耗有10倍差距
非常感谢