In what order does the bitconverter. getbytes method return byte arrays?

Source: Internet
Author: User
Preface

I used the getbytes METHOD OF THE bitconverter class in the zipinteger structure in "talking about zipinteger. At that time, I assume that the getbytes method returns the byte array in different order based on the islittleendian value. However, msdn's documentation on bitconverter classes does not explicitly describe this. For more information, see my post on the msdn Forum "in which order does the bitconverter. getbytes method return byte arrays ":

 
As mentioned in the "biginteger Constructor (byte [])" in the msdn document, each byte in the value array should be in the little-Endian order, from the lowest order byte to the highest order byte. Most methods for converting numeric values to byte arrays, such as biginteger. tobytearray and bitconverter. getbytes, return byte arrays in little-Endian order. According to my understanding, this msdn document assumes that the bitconverter. getbytes method always returns byte arrays in little-Endian order, regardless of the bitconverter. islittleendian value. In the bitconverter Class documentation, the bitconverter. getbytes method does not explicitly specify the sequence in which the byte array should be returned. I wonder if my understanding is correct.

This post does not receive a reliable response.

Test Program

So, let's write a program to test it. Here is bitconvertertester. CS:

 

Using system; namespace skyiv. tester {static class bitconvertertester {static void main () {console. writeline ("OS version:" + environment. osversion); console. writeline ("CLR version:" + environment. version); console. writeline ("islittleendian:" + bitconverter. islittleendian); long n = 0x1234567890abcdef; double D = 1; console. writeline (N. tostring ("X") + ":" + bitconverter. tostring (bitconverter. getbytes (N); console. writeline (D. tostring ("F14") + ":" + bitconverter. tostring (bitconverter. getbytes (D )));}}}

 

This program is compiled and run in the. NET Framework 4 environment of Windows Server 2003 operating system:

C: \ CS \ bitconvertertester>CSC bitconvertertester. CSMicrosoft (r) Visual C #2010 compiler 4.0.30319.1 copyright (c) Microsoft Corporation. All rights reserved. C: \ CS \ bitconvertertester>BitconvertertesterOS Version: Microsoft Windows NT 5.2.3790 Service Pack 2 CLR version: 4.0.30319.1 islittleendian: true1234567890abcdef: EF-CD-AB-90-78-56-34-121.00000000000000: 00-00-00-00-00-f0-3fc: \ CS \ bitconvertertester>

 

Compile and run in the mono 2.8.2 environment of ubuntu 10.10:

 
Ben@ben-m4000t :~ /Work/bitconvertertester $DMCS bitconvertertester. CSBen@ben-m4000t :~ /Work/bitconvertertester $Mono28 bitconvertertester.exeOS Version: Unix 2.6.35.24 CLR version: 4.0.30319.1 islittleendian: true1234567890abcdef: EF-CD-AB-90-78-56-34-121.00000000000000: 00-00-00-00-00-00-f0-3fben @ ben-m4000t :~ /Work/bitconvertertester $

 

The results of these two operations are expected. The getbytes method of the bitconverter class returns the byte array in little-Endian order. However, in these two runs, the islittleendian value is true, so our problem is still not solved.

View related source programs in Microsoft. NET Framework 4 Code

Sacrifice the reflector artifact:

Find the bitconverter class in the system namespace of mscorlib. dll:

As shown in, islittleendian is a static read-only field of the bitconverter class.

As shown in, in the static constructor of the bitconverter class, the value of the static read-only field islittleendian is directly assigned to true. Since Microsoft does not implement the C # source code of the bitconverter class, I do not know whether it is written directly in the Microsoft C # source program or whether it is determined by the platform, however, the C # compiler optimizes this code on a specific platform.

As shown in, the getbytes (int64) method is also very simple, and the corresponding byte array is obtained directly through insecure pointer conversion. Those who have learned the C language must be very familiar with this practice. It is clear that the getbytes method of the bitconverter class returns the byte array according to the different islittleendian values in different order. The description in the msdn document "biginteger Constructor (byte [])": "biginteger. tobytearray and bitconverter. getbytes, returned byte array in the order of little-Endian "is incorrect.

Continue:

The toint64 method in also explicitly takes different actions based on the islittleendian value. In fact, since islittleendian is explicitly assigned true to a static constructor, You can omit the islittleendian judgment here and simply follow the islittleendian value as true, you can save a little bit of code and increase the speed.

We can see that the getbytes (double) method is also very simple.

View related mono 2.8.2 Source code

We can go to the http://ftp.novell.com/pub/mono/sources/mono/ to download the mono source code, and then find the bitconverter class source code in the following way:

Ben@ben-m4000t :~ $CD src/mono-2.8.2Ben@ben-m4000t :~ /Src/mono-2.8.2 $Find.-Name bitconverter. CS./MCS/class/corlib/system/bitconverter. csben @ ben-m4000t :~ /Src/mono-2.8.2 $

Here is bitconverter. CS:

 

/// System. bitconverter. CS // Author: // Matt Kimball (matt@kimball.net) // copyright (c) 2004 Novell, Inc (http://www.novell.com) // permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "software"), to deal in the software without restriction, including // without limitation the rights to use, copy, modify, me RGE, publish, // distriense, sublicense, and/or duplicate copies of the software, and to // permit persons to whom the software is furnished to do so, subject to // The following conditions: // The above copyright notice and this permission notice shall be // encoded in all copies or substantial portions of the software. /// the software is provided "as is", without warranty of any kind, // express or I Mplied, including but not limited to the warranties of // merchantability, fitness for a special purpose and // noninfringement. in no event shall the authors or copyright holders be // liable for any claim, damages or other liability, whether in an action // of contract, tort or otherwise, arising from, out of or in connection // with the software or the use or other dealings in the software. // usin G system. text; namespace system {publicstaticclass bitconverter {static readonly bool swappedwordsindouble = random (); public static readonly bool islittleendian = amilittleendian (); static unsafe bool amilittleendian () {// binary representations of 1.0: // big endian: 3f F0 00 00 00 00 00 00 // little endian: 00 00 00 00 00 F0 3f // arm FPA little endian: 00 00 F0 3f 00 00 00 00 double D = 1.0; byte * B = (byte *) & D; Return (B [0] = 0);} static unsafe bool doublewordsareswapped () {// binary representations of 1.0: // big endian: 3f F0 00 00 00 00 00 00 // little endian: 00 00 00 00 00 F0 3f // arm FPA little endian: 00 00 F0 3f 00 00 00 00 00 double D = 1.0; byte * B = (byte *) & D; return B [2] = 0xf0;} public static long doubletoint64bits (double value) {return toint64 (getbytes (value), 0) ;} Public static double int64bitstodouble (long value) {return todouble (getbytes (value), 0);} internal static double internalint64bitstodouble (long value) {return swappabletodouble (getbytes (value ), 0);} unsafe static byte [] getbytes (byte * PTR, int count) {byte [] ret = new byte [count]; for (INT I = 0; I <count; I ++) {RET [I] = PTR [I];} return ret;} unsafe public static byte [] getbytes (bool value) {Return getbytes (byte *) & Value, 1);} unsafe public static byte [] getbytes (char value) {return getbytes (byte *) & value, 2);} unsafe public static byte [] getbytes (short value) {return getbytes (byte *) & Value, 2 );} unsafe public static byte [] getbytes (INT value) {return getbytes (byte *) & Value, 4);} unsafe public static byte [] getbytes (long value) {return getbytes (byte *) & Value, 8);} [clscompl Iant (false)] unsafe public static byte [] getbytes (ushort value) {return getbytes (byte *) & Value, 2);} [clscompliant (false)] unsafe public static byte [] getbytes (uint value) {return getbytes (byte *) & Value, 4);} [clscompliant (false)] unsafe public static byte [] getbytes (ulong value) {return getbytes (byte *) & Value, 8);} unsafe public static byte [] getbytes (float value) {return getbytes (byte *) & Value, 4);} unsafe public static byte [] getbytes (double value) {If (swappedwordsindouble) {byte [] DATA = new byte [8]; byte * P = (byte *) & value; data [0] = P [4]; data [1] = P [5]; data [2] = P [6]; data [3] = P [7]; data [4] = P [0]; data [5] = P [1]; data [6] = P [2]; data [7] = P [3]; return data;} else {return getbytes (byte *) & value, 8) ;}} unsafe static void putbytes (byte * DST, byte [] SRC, int start _ Index, int count) {If (src = NULL) throw new argumentnullexception ("value"); If (start_index <0 | (start_index> SRC. length-1) throw new argumentoutofrangeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. "); // avoid Integer Overflow (with large POS/neg start_index values) if (SRC. length-count <start_index) throw new argumen Texception ("Destination array is not long" + "enough to copy all the items in the collection. "+" Check array index and length. "); For (INT I = 0; I <count; I ++) DST [I] = SRC [I + start_index];} unsafe public static bool toboolean (byte [] value, int startindex) {If (value = NULL) throw new argumentnullexception ("value "); if (startindex <0 | (startindex> value. length-1) throw new argumentoutofra Ngeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. "); If (value [startindex]! = 0) return true; return false;} unsafe public static char tochar (byte [] value, int startindex) {char ret; putbytes (byte *) & ret, value, startindex, 2); return ret;} unsafe public static short toint16 (byte [] value, int startindex) {short ret; putbytes (byte *) & ret, value, startindex, 2); return ret;} unsafe public static int toint32 (byte [] value, int startindex) {int ret; putbytes (byte *) & ret, value, Startindex, 4); return ret;} unsafe public static long toint64 (byte [] value, int startindex) {long ret; putbytes (byte *) & ret, value, startindex, 8); return ret;} [clscompliant (false)] unsafe public static ushort touint16 (byte [] value, int startindex) {ushort ret; putbytes (byte *) & ret, value, startindex, 2); return ret;} [clscompliant (false)] unsafe public static uint touint32 (byte [] value, int star Tindex) {uint ret; putbytes (byte *) & ret, value, startindex, 4); return ret;} [clscompliant (false)] unsafe public static ulong touint64 (byte [] value, int startindex) {ulong ret; putbytes (byte *) & ret, value, startindex, 8); return ret ;} unsafe public static float tosingle (byte [] value, int startindex) {float ret; putbytes (byte *) & ret, value, startindex, 4); return ret ;} unsafe public static double Double (byte [] value, int startindex) {double ret; If (swappedwordsindouble) {byte * P = (byte *) & ret; If (value = NULL) throw new argumentnullexception ("value"); If (startindex <0 | (startindex> value. length-1) throw new argumentoutofrangeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. "); // avoid Integer Overflow (with large POS/neg start_index values) if (value. length-8 <startindex) throw new argumentexception ("Destination array is not long" + "enough to copy all the items in the collection. "+" Check array index and length. "); P [0] = value [startindex + 4]; P [1] = value [startindex + 5]; P [2] = value [startindex + 6]; P [3] = value [startindex + 7]; P [4] = value [startindex + 0]; P [5] = value [startindex + 1]; P [6] = Value [startindex + 2]; P [7] = value [startindex + 3]; return ret;} putbytes (byte *) & ret, value, startindex, 8); return ret;} unsafe internal static double swappabletodouble (byte [] value, int startindex) {double ret; If (swappedwordsindouble) {byte * P = (byte *) & ret; If (value = NULL) throw new argumentnullexception ("value"); If (startindex <0 | (startindex> value. length-1) Throw New Argument Outofrangeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. "); // avoid Integer Overflow (with large POS/neg start_index values) if (value. length-8 <startindex) throw new argumentexception ("Destination array is not long" + "enough to copy all the items in the collection. "+" Check array index and length. "); P [0] = value [start Index + 4]; P [1] = value [startindex + 5]; P [2] = value [startindex + 6]; P [3] = value [startindex + 7]; P [4] = value [startindex + 0]; P [5] = value [startindex + 1]; P [6] = value [startindex + 2]; P [7] = value [startindex + 3]; return ret;} else if (! Islittleendian) {byte * P = (byte *) & ret; If (value = NULL) throw new argumentnullexception ("value "); if (startindex <0 | (startindex> value. length-1) throw new argumentoutofrangeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. "); // avoid Integer Overflow (with large POS/neg start_index values) if (value. length-8 <startindex) throw new argumentexception ("Destination array is not long" + "enough to copy all the items in the collection. "+" Check array index and length. "); P [0] = value [startindex + 7]; P [1] = value [startindex + 6]; P [2] = value [startindex + 5]; P [3] = value [startindex + 4]; P [4] = value [startindex + 3]; P [5] = value [startindex + 2]; P [6] = value [startindex + 1]; P [7] = value [startindex + 0]; return ret;} putbytes (byte *) & ret, value, startindex, 8); return ret;} public static string tostring (byte [] value) {If (value = NULL) throw new argumentnullexception ("value "); return tostring (value, 0, value. length);} public static string tostring (byte [] value, int startindex) {If (value = NULL) throw new argumentnullexception ("value"); Return tostring (value, startindex, value. length-startindex);} public static string tostring (byte [] value, int startindex, int length) {If (value = NULL) throw new argumentnullexception ("bytearray "); // The 4th and last clause (start_index> = value. length) // was added as a small fix to a very obscure bug. // It makes a small difference when start_index is // outside the range and length = 0. if (startindex <0 | startindex> = value. length) {// special (but valid) Case (e.g. new byte [0]) if (startindex = 0) & (value. length = 0) return string. empty; throw new argumentoutofrangeexception ("startindex", "index was" + "out of range. must be non-negative and less than the "+" Size of the collection. ");} If (length <0) throw new argumentoutofrangeexception (" length "," value must be positive. "); // Note: re-ordered to avoid possible integer overflowif (startindex> value. length-length) throw new argumentexception ("startindex + length> value. length "); If (length = 0) return string. empty; stringbuilder builder = new stringbuilder (length * 3-1); int end = startindex + length; For (INT I = startindex; I <end; I ++) {if (I> startindex) builder. append ('-'); char high = (char) (value [I]> 4) & 0x0f); char low = (char) (value [I] & 0x0f); If (high <10) high + = '0'; else {high-= (char) 10; high + = 'a ';} if (low <10) Low + = '0'; else {LOW-= (char) 10; low + = 'a';} builder. append (high); builder. append (low);} return builder. tostring ();}}}

 

 

We can see that in row 39th, The amilittleendian method of rows 41st to 50 assigns a value to the static read-only field islittleendian. The annotations in this amilittleendian method are clearly written. In fact, there are three platforms, except Big-Endian and little-Endian, there is also an "arm FPA little endian ", here it is also attributed to little-Endian. However, the following methods must be processed by different means.

In addition, unlike Microsoft. NET Framework 4, the various overloaded public static getbytes methods of bitconverter classes in Mono call the Private Static getbytes methods from lines 78th to 87 to implement their functions.

From the mono source code, we can also see that the getbytes method of bitconverter class returns byte arrays in different order based on the value of islittleendian.

Conclusion

To sum up, the msdn document says in the "biginteger Constructor (byte [])": "biginteger. tobytearray and bitconverter. getbytes, returned byte array in the order of little-Endian "is incorrect. The getbytes method of the bitconverter class returns the byte array in different order based on the value of islittleendian.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.