How to convert...

  • Thread starter Thread starter Juan Gabriel Del Cid
  • Start date Start date
J

Juan Gabriel Del Cid

How can I convert a byte array (of length 4) to a to a UInt32?

Use this method:

BitConverter.ToInt32(byte []value, int startIndex)

That takes 4 bytes from startIndex and converts it to an integer.

That should do it,
-JG
 
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

Now there's probably a function for it somewhere ..
 
Michel,

You can use the BitConverter class to do this, like this:

// Get the value from a byte array.
int pintValue = BitConverter.ToInt32(pbytArray, 0);

This assumes your array is named "pbytArray" and you want to get the
integer from the first four bytes.

Hope this helps.
 
psuedonym said:
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

This is much faster than BitConverter.ToUInt32. Turning optimizing on makes
it about five times faster, whereas BitConverter.ToUInt32 only benefits
slightly from the optimize switch. BitConverter.ToUInt32 puts the first byte
in the least-significant position of the UInt32, whereas with your method
you can control it (you've done the reverse in your example).

Another approach that seems like it might be the fastest but is actually
slower than the above (but still way faster than BitConverter) is to use a
union struct to put the bytes in their position:

[StructLayout(LayoutKind.Explicit)]
struct UInt32Bytes
{
[FieldOffset(0)] public UInt32 u;
[FieldOffset(0)] public byte b0;
[FieldOffset(1)] public byte b1;
[FieldOffset(2)] public byte b2;
[FieldOffset(3)] public byte b3;
}

UInt32Bytes ubytes;
ubytes.u = 0;
ubytes.b0 = b[0];
ubytes.b1 = b[1];
ubytes.b2 = b[2];
ubytes.b3 = b[3];
u = ubytes.u;

This isn't worth doing for byte[4] to uint, but might have potential for
some more complex conversions. It's much less readible, though, and the
behavior varies with the machine endianness.
 
Bret Mulvey said:
psuedonym said:
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

This is much faster than BitConverter.ToUInt32. Turning optimizing on makes
it about five times faster, whereas BitConverter.ToUInt32 only benefits
slightly from the optimize switch.

This is very odd - I would have thought the above would be pretty much
exactly what BitConverter.ToUInt32 would do, and that it would all be
inlined. Is it parameter checking which is slowing it down, do you
think?
BitConverter.ToUInt32 puts the first byte
in the least-significant position of the UInt32, whereas with your method
you can control it (you've done the reverse in your example).

It's not even that simple - BitConverter.ToUInt32 will put the first
byte in whichever position it thinks the platform prefers, so you can't
even depend on it doing a single thing across all platforms (if you're
considering non-Windows in the first place, that is). It's always
surprised me that BitConverter doesn't allow you to *set* the
endianness, or that there aren't two separate classes
LittleEndianBitConverter and BigEndianBitConverter.
 
Isnt everything in .NET inline?



Jon Skeet said:
Bret Mulvey said:
psuedonym said:
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

This is much faster than BitConverter.ToUInt32. Turning optimizing on makes
it about five times faster, whereas BitConverter.ToUInt32 only benefits
slightly from the optimize switch.

This is very odd - I would have thought the above would be pretty much
exactly what BitConverter.ToUInt32 would do, and that it would all be
inlined. Is it parameter checking which is slowing it down, do you
think?
BitConverter.ToUInt32 puts the first byte
in the least-significant position of the UInt32, whereas with your method
you can control it (you've done the reverse in your example).

It's not even that simple - BitConverter.ToUInt32 will put the first
byte in whichever position it thinks the platform prefers, so you can't
even depend on it doing a single thing across all platforms (if you're
considering non-Windows in the first place, that is). It's always
surprised me that BitConverter doesn't allow you to *set* the
endianness, or that there aren't two separate classes
LittleEndianBitConverter and BigEndianBitConverter.
 
Roll yer own.


Jon Skeet said:
Bret Mulvey said:
psuedonym said:
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

This is much faster than BitConverter.ToUInt32. Turning optimizing on makes
it about five times faster, whereas BitConverter.ToUInt32 only benefits
slightly from the optimize switch.

This is very odd - I would have thought the above would be pretty much
exactly what BitConverter.ToUInt32 would do, and that it would all be
inlined. Is it parameter checking which is slowing it down, do you
think?
BitConverter.ToUInt32 puts the first byte
in the least-significant position of the UInt32, whereas with your method
you can control it (you've done the reverse in your example).

It's not even that simple - BitConverter.ToUInt32 will put the first
byte in whichever position it thinks the platform prefers, so you can't
even depend on it doing a single thing across all platforms (if you're
considering non-Windows in the first place, that is). It's always
surprised me that BitConverter doesn't allow you to *set* the
endianness, or that there aren't two separate classes
LittleEndianBitConverter and BigEndianBitConverter.
 
news.microsoft.com said:
Isnt everything in .NET inline?

No - I don't think you're talking about "inline" in the same way I am.
I'm talking about the JIT inlining some method/property calls by
replacing the call with the code itself (so that, say, simple access to
a field by way of a property is no less efficient than accessing the
field directly).

The JIT doesn't inline methods over a certain size, or which violate
certain conditions (things like try/catch, throwing exceptions, loops,
conditionals - I can't remember exactly now).
 
news.microsoft.com said:
Roll yer own.

I could certainly do that - but it seems daft for everyone to do that
when MS could perfectly easily do it themselves, once, and everyone
could use that. They clearly recognise the need for this kind of
functionality, but haven't recognised the need for it to be specific in
terms of endianness.
 
I think you will find alot of Daft things in the libraries., its nice to see
some rich classes but what I actually find NECESSARY, just isnt there and am
dropping back to DllImport. So, I spend ALOT of my time doing things they
SHOULD have done in the first place.

The more you look the more you will find that the libraries are a swiss
cheese of funcationality.

In some cases there is gaps so large Darth Vader could pilot the Death Star
through after a binge on a saturday night.
 
news.microsoft.com said:
I think you will find alot of Daft things in the libraries., its nice to see
some rich classes but what I actually find NECESSARY, just isnt there and am
dropping back to DllImport. So, I spend ALOT of my time doing things they
SHOULD have done in the first place.

The more you look the more you will find that the libraries are a swiss
cheese of funcationality.

In some cases there is gaps so large Darth Vader could pilot the Death Star
through after a binge on a saturday night.

I agree there are some holes, although I wouldn't put it as strongly as
you. The one I've banged my head against is the lack of real timezone
support - it's *almost* there, but only if you only want the system
timezone! I would imagine this will be fixed in the next version
though, as many people have been asking for it. (I know there are third
party libraries around to fix this, of course.)
 
I would.

Serial communication for one.


Jon Skeet said:
I agree there are some holes, although I wouldn't put it as strongly as
you. The one I've banged my head against is the lack of real timezone
support - it's *almost* there, but only if you only want the system
timezone! I would imagine this will be fixed in the next version
though, as many people have been asking for it. (I know there are third
party libraries around to fix this, of course.)
 
Bret Mulvey said:
psuedonym said:
In my day we did it like this ;-)

UInt32 u = 0;
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };

u = (UInt32)((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0));

This is much faster than BitConverter.ToUInt32. Turning optimizing on makes
it about five times faster, whereas BitConverter.ToUInt32 only benefits
slightly from the optimize switch. BitConverter.ToUInt32 puts the first byte
in the least-significant position of the UInt32, whereas with your method
you can control it (you've done the reverse in your example).

[snip]

It wouldn't surprise me if BitConverter is multiplying by powers of 2
instead of using shift/or. That'd slow it down some.
 
psuedonym said:
It wouldn't surprise me if BitConverter is multiplying by powers of 2
instead of using shift/or. That'd slow it down some.

You mean like

u = b[0] + b[1] * 0x100U + b[2] * 0x10000U + b[3] * 0x1000000U;

This is actually almost as fast as shifting. In debug mode it's even a
smidge faster.

No, BitConverter is "extern" so I wonder if it's popping out to an unmanaged
code layer. Even if you do all the parameter checking and the whole thing in
C#, it's still only 3x slower than above, instead of 5x or 6x slower like
BitConverter.
 
Bret Mulvey said:
You mean like

u = b[0] + b[1] * 0x100U + b[2] * 0x10000U + b[3] * 0x1000000U;

This is actually almost as fast as shifting. In debug mode it's even a
smidge faster.

No, BitConverter is "extern" so I wonder if it's popping out to an unmanaged
code layer. Even if you do all the parameter checking and the whole thing in
C#, it's still only 3x slower than above, instead of 5x or 6x slower like
BitConverter.

Actually I was thinking more of something like this:

// equates to BitConverter params
Byte[] b = new Byte[4] { 0x0A, 0x0B, 0x0C, 0x0D };
int n = 0; // start index

// local vars
int x = 0; // exponent
UInt32 u = 0; // result

for(int i = 0; i < 4; i++)
{
u += (UInt32)(b[n++] * (2 ^ x));
x += 8;
}
 
Back
Top