nowox
nowox

Reputation: 29116

How to easily extract 2x int16 from a int32?

I have a variable that have 2x int16 values as:

int32_t value = 0x1234ABCD; // a=0x00001234, b=0xFFFFABCD

The naive solution is to do a mask:

int32_t a = (value & 0xFFFF0000) >> 16;
int32_t b = (value & 0x0000FFFF);

But with this, I don't have any sign expansion and b becomes 0x0000ABCD instead of 0xFFFFABCD.

My next attempt was to use an intermediate structure

struct dual_int16 {
   long hi:16;
   long lo:16;
}

int32_t a = (struct dual_int16)value).lo;
int32_t a = (struct dual_int16)value).hi;

Unfortunately my compiler doesn't allow me to do this "struct dual_int16 is not allowed" or "type of cast must be arithmetic or pointer".

Is there any correct way to extract my 2x int16 with sign expansion in C99?

EDIT

Because I am using a specific compiler (ADSP-21xxx) . I don't have all the standard types defined in stdint.h such as int16_t. My compiler does not recognize int8_t and int16_t.

The arch has an hybrid 32-48bits dual ALU, big endian.

Upvotes: 2

Views: 850

Answers (3)

unwind
unwind

Reputation: 400009

If you want signed 16-bit values, use the proper type:

#include <stdint.h>

const int32_t value = 0x1234ABCD; // a=0x00001234, b=0xFFFFABCD

const int16_t a = (value >> 16) & 0xffff;
const int16_t b = value & 0xffff;

printf("a=%hd\nb=%hd\n", (short) a, (short) b);

This prints:

a=4660
b=-21555

Also note that I shift before I mask, to reduce the literal size of the masks. This is probably pointless with modern smart optimizing compilers, but that's the reason I changed it.

I used int16_t since you used uint32_t and mentioned C99, that really made me believe you should have it. Make sure you #include <stdint.h>.

Upvotes: 3

i486
i486

Reputation: 6573

short a = (short)( (value >> 16) & 0xFFFF );
short b = (short)( value & 0xFFFF );

int32_t is not a standard type, as well (comment to @coin). short/short int is equivalent of int16_t.

Upvotes: -2

Jason Hu
Jason Hu

Reputation: 6333

union will do the trick.

union {
    int32_t value;
    struct {
        int16_t v1, v2;
    } decomp;
} extract;

/* ... */
extract.value = value;
int32_t a = extract.decomp.v1, b = extract.decomp.v2;

notice that, a and b have desired signs.

Upvotes: 1

Related Questions