3Byte Two's Compliment


is there a smart way to handle signed 24 bit integers ? (without using "if" etc.)

Seems gcc > 4.7 supports a uint24_t nad int24_t datatype.

My ADC returns 3 Bytes conversion result as int24_t.


"Smart" is highly subjective.

A "simple" way is to hand it to a signed long.


“Smart” is highly subjective.

agree :slight_smile:

void setup() {
  Serial.println("signed 24bit test\n");    
  int32_t value[]={0x800000, 0xFFFFFF, 0x0, 0x000001, 0x7FFFFF}; 
// exp result     -8.388.608,    -1   ,  0 ,    +1   , 8.388.607   
  for(int i=0; i<5; i++) {
    Serial.print(value[i], HEX);
    Serial.println(value[i], DEC);    

signed 24bit test

800000 8388608 // expected -8.388.608
FFFFFF 16777215 // expected -1
0 0
1 1
7FFFFF 8388607

i’, playing around with bit manipulation (shift, toggle, etc.) but
it always end up in requirement to use an IF condition.

“smart” would be without ‘IF’ but a straight conversion line ( or 2)


800000 8388608 // expected -8.388.608

You'd need to do the sign extension yourself, or get the compiler to do it for you, by starting with 32 bit signed vales and truncating to 24. e.g.int32_t value[]={0xFF800000, 0xFFFFFFFF, 0x0, 0x000001, 0x7FFFFF};

What about this:

1) left align the 3 bytes to an unsigned long type. Making sure the last byte is 0. 2) Point a signed long pointer to the unsigned type. 3) right shift the unsigned type.

How about this:

a signed long type = ((signed long) (value << 8)) >> 8;
Essentially the approach I outlined earlier. It creates a left aligned unsigned long type (32-bit). Then it cast it to signed long to preserve the signage. After that, you right shift it to return the right value.
See if it works.


this is exactly what i meant by "smart" :)

Thank you very much wally