开发者

Assigning a value bit by bit

If I have a struct like so:

struct example
{
   uint16_t bar:1;
   uint16_t foo:1;
};

Then I have another 16-bit variable: uint16_t value;

If I want the first bit in "value" to be assigned to "example.bar", and the second bit in value to be assigned to "example.foo", how would I do that?

EDIT:

I tried the following:

typedef struct
{
    unsigned short      in_1_16;
    unsigned short      in_17_32;
    unsigned short      in_33_48;
} READSTR;

typedef struct 
{   
    unsigned short      chan_1_16;
    unsigned short      chan_17_32;
    unsigned short      chan_33_48; 
} TLM;

void main()
{
    TLM tlm;
    tlm.chan_1_16 = 0xFFFF;
    READSTR t675;

    t6开发者_开发知识库75.in_1_16 = 0x10;
    t675.in_17_32 = 0x9;
    t675.in_33_48 = 0x8;

tlm.chan_1_16 |= t675.in_1_16 & 1;
tlm.chan_1_16 |= t675.in_1_16 & (1 << 1);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 2);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 3);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 4);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 5);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 6);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 7);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 8);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 9);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 10);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 11);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 12);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 13);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 14);
tlm.chan_1_16 |= t675.in_1_16 & (1 << 15);
printf("%x", tlm.chan_1_16);

So I am setting the value in on struct to all ones (0xFFFF), and I am trying to set it to 0x10, bit by bit. But when I run this code I still get 0xFFFF. Not sure what I am doing wrong?


It is impossible to tell, because bit fields are very poorly defined by the standard. The following, you cannot know:

  • whether bit field int is treated as signed or unsigned int
  • the bit order (lsb is where?)
  • whether the bit field can reach past the memory alignment of the CPU or not
  • the alignment of non-bit field members of the struct
  • the memory alignment of bit fields (to the left or to the right?)
  • the endianess of bit fields
  • whether plain int values assigned to them are interpreted as signed or unsigned
  • how bit fields are promoted implicitly by the integer promotions
  • whether signed bit fields are one’s complement or two’s complement
  • location of padding bytes
  • how padding bits are treated
  • values of padding bits
  • and so on

As you hopefully can tell, bit fields are very very bad and shouldn't be used ever. The only sensible solution is to re-write the code without bit fields:

#define FOO 0x01U
#define BAR 0x02U

uint16_t value;

value |= FOO; /* set FOO bit */
value &= ~FOO; /* clear FOO bit */

The above code can be executed on any C/C++ compiler for any system in the world and you will get the expected result.


#include <iostream>

typedef unsigned short uint16;

struct example
{
   uint16 bar:1;
   uint16 foo:1;
};

union foo
{
    struct example x;
    uint16 value;
};

int main()
{
    uint16 bar = 0x01;

    foo f;
    f.value = bar;

    std::cout << f.x.bar << std::endl; // display 1
    std::cout << f.x.foo << std::endl; // display 0
}

EDIT
This snippet was used in production code and it used to work as intended. Anyway, it was tested with static assert and unit-tests that guaranteed its correctness. Since they're not reported here, I agree it should not be used "as is".

Since you (the OP) mentioned C++, I suggest to use std::bitset class:

#include <bitset>

int main()
{
    std::bitset<16> set(bar);

    example x;
    x.bar = set[0];
    x.foo = set[1];

    std::cout << x.bar << std::endl; // display 1
    std::cout << x.foo << std::endl; // display 0
}


try it with:

struct example x;
x.bar = value & 1;
x.foo = value & 1 << 1;

fooN = value & 1 << N;


Values assigned to unsigned bitfields are defined to be reduced modulo 2**N, where N is the number of bits in the bitfield. This means that if you assign an unsigned number to an unsigned bitfield, the least significant N bits of the original number will be used.

So, given struct example x, if you want the least significant bit of value to be placed in x.bar you can simply do:

x.bar = value;

If you want the second-least-significant bit of value to be placed in x.foo, you can likewise use:

x.foo = value >> 1;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜