tags:

views:

985

answers:

6
+2  Q: 

C# 3 byte Ints

I am working on a project where I need to deal at the byte level with integers. Since saving space is a primary consideration, I only need very small (and variable length ints).

Is there a way that I can turn the int '4096' into 3 bytes? or '1053' into a 2 bytes?

Obviously I cna do it manually = (byte[0] * 256) + (byte[1]), but i was wondering if there is an easier option to convert the int into x bytes and back again?

+10  A: 

Can you? Sure. Will it save any space? Maybe, depending on how much work you want to do. You have to understand that the processor is 32-bit, meaning it has 4 byte registers, so that's how it's going to want to store and access things. To force a 3-byte "int" you'll have to keep it in a byte array, and extract it from the array to an aligned address before use. That means that if you store it short, the compiler will either pad it out (and you'll lose any efficiency you think you've created) or it will be a lot slower to read and write.

If this is a desktop app, how exactly is saving space a primary consideration, especially when talking 1 byte per element? The perf penalty for element access may change you mind about how critical that one byte is.

I'd argue that if that 1 byte truly is important, that maybe, just maybe, you're using the wrong language anyway. The number of bytes you'd save my not installing and using the CLR in the first place is a lot of those bytes.

Side note: You'd also do a shift, not a multiplication (though the compiler would likely get there for you).

ctacke
+1  A: 

You have to do some bit shifting. It is much easir if you work with HEX, since every number(I mean every digit, but digit is for base 10, hexgit) represent four bits.

Igor Zelaya
+3  A: 

BitConverter.GetBytes will get you the bytes.

and

BitConverter.ToInt32 will get you a 32 bit int from the bytes.

Allain Lalonde
+2  A: 

Yeah thanks guys. ctacke, you make a perfect point and I think that I am best sticking to standard sized data types.

I did some playing arround with the BitConverter class (http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx) and after some tests with ushorts, and uints I found that they meet the scope of what I am trying to acheive anyway with less bytes anyway.

Initally, I thought I would need a minimum of 16 bytes to do what I want to do, but using ushorts, I've cut this down to 12.

What I've learned today: compilers know wtf they are doing - even the .Net one ;)

Ash
+3  A: 

You could do variable length integer encoding. The old method from years ago was to use the high bit of each byte to denote that the integer continues to another byte. So you lose one bit per byte, but gain small integers. This is mostly useful in persistent storage where every last byte counts.

Example: Assume we are dealing with unsigned integers, we would have

int  binary
0    00000000
1    00000000
...  
127  01111111
128  00000001 10000000
129  00000001 10000001
...
255  00000001 11111111
256  00000010 10000000
...
16383 01111111 11111111
16384 00000001 10000000 10000000

so 0-127 take 1 byte and 128-16383 takes 2 bytes, etc...

For more complex ways of doing this check out this page

Amir
+2  A: 

Just for added insanity, let's do it in C# using the old C-style union trick:

[StructLayout(LayoutKind.Explicit)]
struct OddUnion
{
    /* The 32-bit integer value */
    [FieldOffset(0)]
    public int IntegerValue;

    /* The bytes that overlap with it */
    [FieldOffset(0)]
    public byte Byte1;
    [FieldOffset(1)]
    public byte Byte2;
    [FieldOffset(2)]
    public byte Byte3;
    [FieldOffset(3)]
    public byte Byte4;
 }

And then, when you want to "convert", do this:

OddUnion myOddUnion;
myOddUnion.IntegerValue = 4096;
Byte secondByte = myOddUnion.Byte1;

But that really only helps if you're looking to "save" the cost of bit-shifting out a single byte from a word. I haven't looked at the generated SMIL, so I don't know whether this is any cheaper in comparison to any other solution.

scraimer
Wow man! Smart move!!!
Jonathan C Dickinson
I'd call it "clever" instead and say that this is a maintenance nightmare.
ctacke
@ctacke: yup! Totally not worth it, unless you're doing something with an very odd bit/byte/word format. And even then, still not recommended.
scraimer
If you'll ever run this code on a big endian device (unlikely in the case of C#, but not entirely impossible) this will break, of corse.
DrJokepu