Home > Software engineering >  Convert 8 bit signed integer to unsigned and then convert to int32
Convert 8 bit signed integer to unsigned and then convert to int32

Time:11-10

I have a signed 8-bit integer (int8_t) -- which can be any value from -5 to 5 -- and need to convert it to an unsigned 8-bit integer (uint8_t).

This uint8_t value then gets passed to another piece of hardware (which can only handle 32-bit types) and needs to be converted to a int32_t.

How can I do this?

Example code:

#include <stdio.h>
#include <stdint.h>

void main() {

    int8_t input;
    uint8_t package;
    int32_t output;

    input = -5;
    package = (uint8_t)input;
    output = (int32_t)package;

    printf("output = %d",output);
}

In this example, I start with -5. It temporarily gets cast to 251 so it can be packaged as a uint8_t. This data then gets sent to another piece of hardware where I can't use (int8_t) to cast the 8-bit unsigned integer back to signed before casting to int32_t. Ultimately, I want to be able to obtain the original -5 value.

For more info, the receiving hardware is a SHARC processor which doesn't allow int8_t - see https://ez.analog.com/dsp/sharc-processors/f/q-a/118470/error-using-stdint-h-types

The smallest addressable memory unit on the SHARC processor is 32 bits, which means that the minimum size of any data type is 32 bits. This applies to the native C types like char and short. Because the types "int8_t", "uint16_t" specify that the size of the type must be 8 bits and 16 bits respectively, they cannot be supported for SHARC.

CodePudding user response:

Here is one possible branch-free conversion:

output = package; // range 0 to 255
output -= (output & 0x80) << 1;

The second line will subtract 256 if bit 7 is set, e.g.:

  • 251 has bit 7 set, 251 - 256 = -5
  • 5 has bit 7 clear, 5 - 0 = 5

CodePudding user response:

If you want to get the negative sign back using 32-bit operations, you could do something like this:

   output = (int32_t)package;
   if (output & 0x80) { /* char sign bit set */
        output |= 0xffffff00;
   }

   printf("output = %d",output);

CodePudding user response:

Since your receiver platform does not have types that are less than 32 bits wide, your simplest option is to solve this problem on the sender:

int8_t input = -5;
int32_t input_extended = input;
uint8_t buffer[4];

memcpy(buffer, &input_extended, 4);

send_data(buffer, 4);

Then on the receiving end you can simply treat the data as a single int32_t:

int32_t received_data;

receive_data(&received_data, 4);

All of this is assuming that your sender and receiver share the same endianness. If not, you will have to flip the endianness in the sender before sending:

int8_t input = -5;
int32_t input_extended = input;
uint32_t tmp = (uint32_t)input_extended;

tmp = ((tmp >> 24) & 0x000000ff)
    | ((tmp >>  8) & 0x0000ff00)
    | ((tmp <<  8) & 0x00ff0000)
    | ((tmp << 24) & 0xff000000);

uint8_t buffer[4];

memcpy(buffer, &tmp, 4);

send_data(buffer, 4);

CodePudding user response:

Just subtract 256 from the value, because in 2's complement an n-bit negative value v is stored as 2n - v

input = -5;
package = (uint8_t)input;
output = package > 127 ? (int32_t)package - 256 : package;

CodePudding user response:

EDIT:

If the issue is that your code has if statements for values of -5 to 5, than the simplest solution might be to test for result 5 and change the if statements to values between 0 and 10.

This is probably what the compiler will do when optimizing (since values of 0-10 can be converted to a map, avoiding if statements and minimizing predictive CPU flushing).


Original:

Type casting will work if first cast to uint8_t and then uint32_t...

output = (int32_t)(uint32_t)(uint8_t)input;

Of course, if the 8th bit is set it will remain set, but the sign won't be extended since the type casting operation is telling the compiler to treat the 8th bit as a regular bit (it is unsigned).

Of course, you can always have fun with bit masking if you want to be even more strict, but that's essentially a waste or CPU cycles.

The code:

#include <stdint.h>
#include <stdio.h>

void main() {

  int8_t input;
  int32_t output;

  input = -5;
  output = (int32_t)(uint32_t)(uint8_t)input;

  printf("output = %d\n", output);
}

Results in "output = 251".

  • Related