5

I have some bitfield:

int somefield : 15;

I'm trying to convert an int to 15 bit (can be positive or negative).

What is the best practice to do it efficiently?

mibo6700
  • 123
  • 1
  • 2
  • 9
  • 2
    Assign the `int` to the bitfield? It's possibly implementation-defined, but that's bitfields for you. – EOF Mar 17 '16 at 16:06
  • that exactly the way I did it, but the compiler reports error (in visual studio), but in other machine, it is OK (emacs + gcc).... So it is machine depended and I'm trying to do it independent.... (But all machines are LSB) – mibo6700 Mar 17 '16 at 16:16
  • 1
    If the bitfield is unsigned, what do you want to happen if the int value you try to assign to it is negative? – Steve Summit Mar 17 '16 at 16:18
  • What exactly is the error in visual studio? – EOF Mar 17 '16 at 16:23
  • 1
    http://stackoverflow.com/questions/10851396/how-to-assign-value-to-a-struct-with-bit-fields – fukanchik Mar 17 '16 at 16:23
  • Thanks a lot! The answer there is for c++. Is this part of implementation is identical to c? – mibo6700 Mar 17 '16 at 16:37
  • @mibo6700 The accepted answer in that post doesn't use any C++-only features, but it *does* assume that bitfields of type `uint32_t` are permissible, which is not standard. It also requires that the bitfields are unsigned, or the behavior will be implementation-defined. – EOF Mar 17 '16 at 16:40
  • 1
    "Can I really use an unsigned int in this case - NO I CAN'T!" --> Why not? Without an answwer to this, I see the question as unclear. – chux - Reinstate Monica Mar 17 '16 at 16:40
  • Note: your bitfield is not unsigned. – joop Mar 17 '16 at 16:41
  • @joop: Note: Whether the OP's bitfield is unsigned is implementation-defined. C11 draft standard n1570: `6.7.2 Type specifiers, 5 Each of the comma-separated multisets designates the same type, except that for bit-fields, it is implementation-defined whether the specifier int designates the same type as signed int or the same type as unsigned int.` – EOF Mar 17 '16 at 16:41
  • I think that when it is a negative number, I have to convert it to positive, than to 15 bits and than to make it negative again (2's complement in my case). So I can use unsigned int, but the solution has to be different than "just assignment".... – mibo6700 Mar 17 '16 at 16:44

2 Answers2

4

I'm trying to convert an int to 15 bit (can be positive or negative). What is the best practice to do it efficiently?

If the int to convert is within the range of a 15-bit signed integer, simple use the following code. It is important not to use int without signed in defining the bit-field as this is one place in the C spec, it makes a difference. Without the signed, an int bit field could be implemented as unsigned. It is implementation defined.

signed int somefield:15;
...
x.somefield = 12345;
int y = x.somefield;

If the int to convert may be outside than the range of a 15-bit signed integer, better to use an unsigned field to have portably consistent defined behavior. It is unclear what value OP wants to store when the int is out-of-range. Some additional code may be needed should the sign need to be recovered. No additional overhead on writing and maybe overhead on reading depending on coding needs.

unsigned somefield:15;
...
x.somefield = 123456;

x.somefield = -1;
int y = x.somefield >= 0x4000 ? x.somefield - 0x8000 : x.somefield;

Alternatively, if the value to assign may be outside the bit-field range, insure the assignment does not happen. Additional overhead on writing and none on reading.

signed int somefield 15;
...
if (i >= INT15_MIN && i <= INT15_MAX) x.somefield = i;
else TBD();

int y = x.somefield;
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Assignment to a signed type that can't represent the value is *not* undefined. It's implementation-defined. – EOF Mar 17 '16 at 17:13
0

chux, thanks a lot! I've found out another option, and it looks pretty simple too:

typedef struct {
    unsigned int firstletter: 5;
    unsigned int secondletter: 5;
    unsigned int thirdletter: 5;
  } data_in_32_format;

typedef struct {
    unsigned int somedata: 15;
  } data;

typedef union {
    data_in_32_format;
    data;
  } common_data;

So, when I'm writing the data itself, I'm writing to the:

common_data entry;
entry.data = getint_in_decimal_format;

Than I'm printing it in 32 format:

print32("%c%c%c\n", entry.data_in_32_format.thirdletter
                  , entry.data_in_32_format.secondletter
                  , entry.data_in_32_format.firstletter);

Of cause I need to convert it to char correctly before previous (0-9 => numbers, >9 - letters, so in ASCII it is needed to be +55 to represent 32 bit format correctly (A for 10 and etc.).

mibo6700
  • 123
  • 1
  • 2
  • 9