3

I have a 10 bit signed value. It's actually a 10 bit color value that i want to convert to an int.

The 10 bits are to be interpreted as a signed value within a larger int, where the other bits are zero.

I can think of 3 ways, shown here:

#include <stdio.h>

void p(int v)
{
    printf("\t%d", v);
}

int main()
{
    for (int i = -2; i < 3; ++i)
    {
        unsigned int u = i & 0x3ff;

        int v;

        // method 1: test the bit
        v = u;
        if (u & 0x200) v = v ^ -0x400;
        p(v);

        // method 2: shift
        v = u<<(sizeof(int)*8-10);
        v >>= (sizeof(int)*8-10);
        p(v);

        // method 3: use sign extend
        v = (signed char)(u >> 2);
        v <<= 2;
        v |= u;
        p(v);


        printf("\n");

    }

    return 0;
}

is there a better way? Often there is with this bit twiddling problems.

Thanks for any input.

Update

Adding two more methods. The first suggested by @cruz-jean is bit fields, and the second suggested by gcc after compiling the bitfields.

      // method 4: bit fields
        struct { int v:10; } f;
        f.v = u;
        v = f.v;

        // method 5: sign extend short
        v = (signed short)(u << 6);
        v >>= 6;

Out of interest it appears MSVC compiles #4 into #2 and gcc compiles #4 into #5.

Method 5 looks good.

TonyK
  • 16,761
  • 4
  • 37
  • 72
jkj yuio
  • 2,543
  • 5
  • 32
  • 49
  • 2
    Do you mean `C` or `C++`? I doubt the question should have both tags. – Fred Larson Mar 15 '19 at 20:21
  • If you have a 10 bit signed value and you wanna convert it to an int you only need to cast, nothing else. Sign extension only means increasing the number of bits while retaining value and sign so.. – Fredrik Mar 15 '19 at 20:23
  • 1
    If this value is part of structure bit field, you may simplify it quite a bit by simply declaring it as signed bit field - C/C++ will do all conversions automatically. – mvp Mar 15 '19 at 20:25
  • @Fredrik I meant that the 10 bits are to be interpreted as signed not that it fills the whole word. Sorry if unclear. – jkj yuio Mar 15 '19 at 20:30
  • 10 bit signed value is already an int. What is troubling you? Or do you mean that you have 10-bit encoding of a number? Than what encoding are you using? – SergeyA Mar 15 '19 at 20:30
  • 1
    @FredLarson It's true my test program wont compile as C, but the idea is valid for both. – jkj yuio Mar 15 '19 at 20:31
  • `v = (u & 0x200) ? u - 0x400 : u;` – user3386109 Mar 15 '19 at 20:32
  • @SergeyA I added some clarification to the question. thanks. – jkj yuio Mar 15 '19 at 20:33
  • What's your criteria for "better"? Fastest? Least code? Easiest to read? Easiest to write? Most portable? – Adrian McCarthy Mar 15 '19 at 20:35
  • @AdrianMcCarthy You missed "doesn't invoke implementation-defined behavior or undefined behavior". All of OP's solutions have one or the other. – user3386109 Mar 15 '19 at 20:37
  • @user3386109: Those fall under "Most portable." – Adrian McCarthy Mar 15 '19 at 20:39
  • @AdrianMcCarthy Good point. I think i mean; order by (portable, fastest). – jkj yuio Mar 15 '19 at 20:46
  • Actually I was first to suggest bit fields. But I don't really care – mvp Mar 15 '19 at 23:08
  • Possible duplicate of [Sign extend a nine-bit number in C](https://stackoverflow.com/questions/5814072/sign-extend-a-nine-bit-number-in-c) – phuclv Mar 16 '19 at 00:42
  • other duplicates: [Sign-extend a number in C](https://stackoverflow.com/q/16220983/995714), [Signed Extension from 24 bit to 32 bit in C++](https://stackoverflow.com/q/42534749/995714), https://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend – phuclv Mar 16 '19 at 00:43

2 Answers2

3

You could declare a 10-bit signed bitfield helper type and access the value as an int:

struct signed_10_bit
{
    int val : 10;
};

int some_10_bit_num = 0x3ff;
int extended = signed_10_bit{ some_10_bit_num }.val;
Cruz Jean
  • 2,761
  • 12
  • 16
3

Another one to try:

v = u | (0 - (u&0x200));

good for cpus where shift is slow.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • I like it! Method #1 was motivated by slow shifts, but i didnt like the test. This is better. Some old CPUs can only shift 1 at a time and need a shift loop, so this would be the best way there. Not sure what the bitfields would generate on those. – jkj yuio Mar 17 '19 at 13:49