8

I have a project that I am working on where I require a data type that doesn't exist in the .NET BCL - an Unsigned Int24. For calculations that I am doing, the 4th byte in an int32, even when set to all zeroes, screws up my results.

EDIT: I'm doing bitwise circular shifts on a 24bit integer space that is limited to only 24bits. If the rotation is performed at 24bit level on a 32bit number the result is wildly incorrect.

Does anyone know of any third party implementations of this data type that are available?

Thanks!

TheNerd
  • 339
  • 4
  • 16
  • 3
    How can a fourth byte screw things up? Are you marshalling to unmanaged code? If not, maybe explain a bit further why `[U]Int32` will not work. – nneonneo Sep 23 '12 at 02:19
  • Perhaps [this question](http://stackoverflow.com/q/4378218/62576) can offer some ideas on how to implement it yourself, although I can't see any reason a 4th byte in an int32 would cause problems unless you're doing something wrong. It's hard to say, though, because you posted zero code that demonstrates how it "screws things up". – Ken White Sep 23 '12 at 02:22
  • Seeming as .NET is little-endian on x86 a fourth MSB shouldn't cause any problems unless the library's defined 24-bit handling code makes assumptions about the memory layout. – Dai Sep 23 '12 at 02:27
  • The CPU does not have a 24-bit rotate instruction so there's no benefit in trying to simulate a 24-bit integer in C#. – Gabe Sep 23 '12 at 03:08
  • Your assumption would be incorrect since I have implemented my own rotate implementation. Trying to simulate a 24bit int is exactly what I need. – TheNerd Sep 23 '12 at 11:29

1 Answers1

10

Implementing Int24 isn't hard (honest!). But we need to know more about why you need to implement it. @nneonneo wonders if you're trying to interface with a native library that uses 24-bit integers. If that's the case then you can be done by doing something like this:

[StructLayout(LayoutKind.Sequential)]
public struct UInt24 {
    private Byte _b0;
    private Byte _b1;
    private Byte _b2;

    public UInt24(UInt32 value) {
        _b0 = (byte)( (value      ) & 0xFF );
        _b1 = (byte)( (value >>  8) & 0xFF ); 
        _b2 = (byte)( (value >> 16) & 0xFF );
    }

    public unsafe Byte* Byte0 { get { return &_b0; } }

    public UInt32 Value { get { return _b0 | ( _b1 << 8 ) | ( _b2 << 16 ); } }
}

// Usage:

[DllImport("foo.dll")]
public static unsafe void SomeImportedFunction(byte* uint24Value);

UInt24 uint24 = new UInt24( 123 );
SomeImportedFunction( uint24.Byte0 );

Modifying the class for big-endian or signed Int24 is an exercise left up to the reader.

Dai
  • 141,631
  • 28
  • 261
  • 374
  • I'm doing circular shifts (the rotate command in ASM) on 24bit color values for an experiment that I am working on - the experiment requires that I work in no more than 24bit space. If I perform a rotation meant for 24bits on a 32bit number with zeroes, the resulting number is incorrect. – TheNerd Sep 23 '12 at 02:34
  • That's something you could implement yourself by performing bitshifts on individual bytes and manipulating the results (and overflows) such that the effect is maintained. That said, can't you use 32-bit ARGB values in your environment? – Dai Sep 23 '12 at 03:18
  • Unfortunately not with the hardware that this will output to - a 24bit width pipeline is all that is available. Your answer helps out a lot though - thanks! – TheNerd Sep 23 '12 at 11:34
  • I get Compiler Error CS0212 saying that I need a fixed statement initializer. Not finding much info on what a "fixed statement initializer is" – Goku Dec 10 '19 at 00:17
  • @Goku You need to either compile with the `/unsafe` switch or use a `fixed( byte* b = yourUint24Value.Byte0 )` statement. – Dai Dec 10 '19 at 00:26
  • The offending line is "public unsafe Byte* Byte0 { get { return &_b0; } }" – Goku Dec 10 '19 at 00:31
  • @Goku Ah - yes. That requires the `/unsafe` compiler switch. – Dai Dec 10 '19 at 07:59