Bitwise operation question...

G

gilad

I am trying to return 8 bytes (64 bits) as a 'long' from a file my
program is reading. The logic I am using is below:

return (long)(
((inBytes[0] & 255) << 56) |
((inBytes[1] & 255) << 48) |
((inBytes[2] & 255) << 40) |
((inBytes[3] & 255) << 32) |
((inBytes[4] & 255) << 24) |
((inBytes[5] & 255) << 16) |
((inBytes[6] & 255) << 8) |
((inBytes[7] & 255))
);

The best I am getting from the above is a 32 bit number. I've done some
testing using the first byte, returning it, checking out its bit
pattern, and then checking its bit pattern when shifted by 56, e.g.

Console.WriteLine(
(ulong)(((inBytes[0]&255)<<56)) + " " + (int)inBytes[0]);

and the bit patterns match, but I am only getting the equivalent of 32
bits returned. For example, my output from the above statement might read:

1224736768 73

where

1224736768 = (ulong)(((inBytes[0]&255)<<56))

and

73 = (int)inBytes[0]

When I feed these numbers into Calculator and get their bit patterns
they are:

73 = 1001001

and

1224736768 = 1001001000000000000000000000000

So you can see the shifting seems to be working, there are just not
enough 0s following the shifted number. I've read on MSDN the document
about shifting that says

"If expr is an int or uint (32-bit quantity), the shift count is given
by the low-order five bits of count (count & 0x1f).

If expr is a long or ulong (64-bit quantity), the shift count is given
by the low-order six bits of count (count & 0x3f)."

but 56 as "expr" above equals 111000, which should(?) be used to
calculate 56 bit positions. Anyway, I can't figure out how to get this
working. Any suggestions or alternatives would be appreciated. Thanks,

James
 
J

Jay B. Harlow [MVP - Outlook]

James,
I would use BitConverter.ToInt64.

Something like:

long l = BitConverter.ToInt64(inBytes, 0);

Hope this helps
Jay
 
D

David Browne

I am trying to return 8 bytes (64 bits) as a 'long' from a file my program
is reading. The logic I am using is below:

First off, if the number is stored in Little Endian byte order, you can just
use:

return BitConverter.ToInt64(inBytes,0);


For BigEndian, you almost have it, you just need to convert each byte to a
long before bit shifting.

long l = (long)(
((inBytes[0] & 255L) << 56) |
((inBytes[1] & 255L) << 48) |
((inBytes[2] & 255L) << 40) |
((inBytes[3] & 255L) << 32) |
((inBytes[4] & 255L) << 24) |
((inBytes[5] & 255L) << 16) |
((inBytes[6] & 255L) << 8) |
((inBytes[7] & 255L))
);


David
 
G

gilad

Jay said:
I would use BitConverter.ToInt64.

Something like:

long l = BitConverter.ToInt64(inBytes, 0);

I guess that would be quite a bit simpler, wouldn't it? Actually, after
my post, I changed the return type from long to ulong, and the numbers
straightened up...? Thanks.
 
G

gilad

David said:
For BigEndian, you almost have it, you just need to convert each byte to a
long before bit shifting.

long l = (long)(
((inBytes[0] & 255L) << 56) |
((inBytes[1] & 255L) << 48) |
((inBytes[2] & 255L) << 40) |
((inBytes[3] & 255L) << 32) |
((inBytes[4] & 255L) << 24) |
((inBytes[5] & 255L) << 16) |
((inBytes[6] & 255L) << 8) |
((inBytes[7] & 255L))
);

If I weren't going to use the BitConverter (which I will be, I just want
to understand this), shifting I showed should work for Little Endian
format, correct? I switched the output to ulong, and it seemed to work.
Why I'm not sure.
 
J

Jon Skeet [C# MVP]

David said:
For BigEndian, you almost have it, you just need to convert each byte to a
long before bit shifting.

long l = (long)(
((inBytes[0] & 255L) << 56) |
((inBytes[1] & 255L) << 48) |
((inBytes[2] & 255L) << 40) |
((inBytes[3] & 255L) << 32) |
((inBytes[4] & 255L) << 24) |
((inBytes[5] & 255L) << 16) |
((inBytes[6] & 255L) << 8) |
((inBytes[7] & 255L))
);

If I weren't going to use the BitConverter (which I will be, I just want
to understand this), shifting I showed should work for Little Endian
format, correct? I switched the output to ulong, and it seemed to work.
Why I'm not sure.

*Just* switching to ulong shouldn't have fixed it, but the & 255L
instead of & 255 on each line probably made the real difference - it
meant you were shifting longs rather than ints.

Note that if you want to use a BitConverter-like interface but with a
specific endianness, you can use my EndianBitConverter:

http://www.pobox.com/~skeet/csharp/miscutil
 
G

gilad

Jon said:
*Just* switching to ulong shouldn't have fixed it, but the & 255L
instead of & 255 on each line probably made the real difference - it
meant you were shifting longs rather than ints.

Ah, that makes better sense. Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top