Reputation: 151
Here is a method -
using System;
class Program
{
static void Main(string[] args)
{
//
// Create an array of four bytes.
// ... Then convert it into an integer and unsigned integer.
//
byte[] array = new byte[4];
array[0] = 1; // Lowest
array[1] = 64;
array[2] = 0;
array[3] = 0; // Sign bit
//
// Use BitConverter to convert the bytes to an int and a uint.
// ... The int and uint can have different values if the sign bit differs.
//
int result1 = BitConverter.ToInt32(array, 0); // Start at first index
uint result2 = BitConverter.ToUInt32(array, 0); // First index
Console.WriteLine(result1);
Console.WriteLine(result2);
Console.ReadLine();
}
}
Output
16385 16385
I just want to know how this is happening?
Upvotes: 15
Views: 17327
Reputation: 18563
You can look for yourself - https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,e8230d40857425ba
If the data is word-aligned, it will simply cast the memory pointer to an int32.
return *((int *) pbyte);
Otherwise, it uses bitwise logic from the byte memory pointer values.
Upvotes: 0
Reputation: 22556
For those of you who are having trouble with Little Endien and Big Endien. I use the following wrapper functions to take care of it.
public static Int16 ToInt16(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt16(data, offset);
}
public static Int32 ToInt32(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt32(data, offset);
}
public static Int64 ToInt64(byte[] data, int offset)
{
if (BitConverter.IsLittleEndian)
{
return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0);
}
return BitConverter.ToInt64(data, offset);
}
Upvotes: -1
Reputation: 25834
Looking at the .Net 4.0 Framework reference source, BitConverter
does work how Jon's answer said, though it uses pointers (unsafe
code) to work with the array.
However, if the second argument (i.e., startindex
) is divisible by 4 (as is the case in your example), the framework takes a shortcut. It takes a byte
pointer to the value[startindex]
, casts it to an int
pointer, then dereferences it. This trick works regardless of whether IsLittleEndian
is true.
From a high level, this basically just means the code is pointing at 4 bytes in the byte
array and categorically declaring, "the chunk of memory over there is an int
!" (and then returning a copy of it). This makes perfect sense when you take into account that under the hood, an int
is just a chunk of memory.
Below is the source code of the framework ToUint32
method:
return (uint)ToInt32(value, startIndex);
Upvotes: 3
Reputation: 2551
array[0] = 1; // Lowest // 0x01
array[1] = 64; // 0x40
array[2] = 0; // 0x00
array[3] = 0; // Sign bit 0x00
If you combine each hex value 0x00004001
The MSDN documentatin explains everything
Upvotes: 0
Reputation: 1500695
The docs for BitConverter.ToInt32
actually have some pretty good examples. Assuming BitConverter.IsLittleEndian
returns true, array[0]
is the least significant byte, as you've shown... although array[3]
isn't just the sign bit, it's the most significant byte which includes the sign bit (as bit 7) but the rest of the bits are for magnitude.
So in your case, the least significant byte is 1, and the next byte is 64 - so the result is:
( 1 * (1 << 0) ) + // Bottom 8 bits
(64 * (1 << 8) ) + // Next 8 bits, i.e. multiply by 256
( 0 * (1 << 16)) + // Next 8 bits, i.e. multiply by 65,536
( 0 * (1 << 24)) // Top 7 bits and sign bit, multiply by 16,777,216
which is 16385. If the sign bit were set, you'd need to consider the two cases differently, but in this case it's simple.
Upvotes: 16
Reputation: 149
It converts like it was a number in base 256. So in your case : 1+64*256 = 16385
Upvotes: 4