逐位分配值

时间:2011-02-02 15:22:11

标签: c++ c

如果我有这样的结构:

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

然后我有另一个16位变量:uint16_t value;

如果我希望将“value”中的第一位分配给“example.bar”,并将值中的第二位分配给“example.foo”,我该怎么做?

编辑:

我尝试了以下内容:

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;

    t675.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);

所以我将struct中的值设置为全1(0xFFFF),我试图将它设置为0x10,一点一滴。但是当我运行这段代码时,我仍然得到0xFFFF。不确定我做错了什么?

4 个答案:

答案 0 :(得分:3)

这是不可能的,因为标准定义了很少的位字段。以下,你不可能知道:

  • 是否将bit field int视为signed或unsigned int
  • 位顺序(lsb在哪里?)
  • 位字段是否可以超过CPU的内存对齐
  • struct
  • 的非位字段成员的对齐方式
  • 位字段的内存对齐方式(向左还是向右?)
  • 位字段的字节顺序
  • 分配给它们的普通int值是否被解释为有符号或无符号
  • 整数促销如何隐式提升位字段
  • 有符号位字段是一个补码还是两个补码
  • 填充字节的位置
  • 如何处理填充位
  • 填充位的值

正如您所希望的那样,位字段非常糟糕,不应该永远使用。唯一合理的解决方案是重新编写没有位字段的代码:

#define FOO 0x01U
#define BAR 0x02U

uint16_t value;

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

上述代码可以在世界上任何系统的任何C / C ++编译器上执行,您将获得预期的结果。

答案 1 :(得分:1)

#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
}

修改
此代码段用于生产代码,它曾用于按预期工作。无论如何,它使用静态断言和单元测试进行了测试,保证了它的正确性。由于这里没有报道,我同意不应该“按原样”使用。

由于您(OP)提到了C ++,我建议使用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
}

答案 2 :(得分:0)

尝试:

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

fooN = value & 1 << N;

答案 3 :(得分:0)

分配给无符号位域的值被定义为以2 ** N为模减少,其中N是位域中的位数。这意味着如果将无符号数分配给无符号位域,则将使用原始数字的最低有效N位。

因此,在给定struct example x的情况下,如果您希望将value的最低有效位置于x.bar,则可以执行以下操作:

x.bar = value;

如果您希望将value的第二个最低有效位放在x.foo中,您同样可以使用:

x.foo = value >> 1;