我无法在C语言中操作位域

3

我想用C语言实现LFSR(线性反馈移位寄存器)以生成随机比特。但是当我尝试修改单个比特或将短值分配给内存块时,所有的比特都会被设置为1。如何防止这种情况发生?

struct lfsr{
    //... 
    union{
        unsigned short ff_0 : 1;
        unsigned short ff_1 : 1;
        //... 
        unsigned short ff_f : 1;
        unsigned short ff;
    }flip_flops;
};

int main() {
    struct lfsr gen;
    gen.flip_flops.ff = 1;      //all the ff's set to 1
    gen.flip_flops.ff = htons(0x0001);//all the ff's set to 1
    gen.flip_flops.f_0 = 1;     //all the ff's set to 1
    gen.flip_flops.f_0 = 0;     //all the ff's set to 0
}

2
为什么使用union来处理位域?我会使用struct - prog-fh
@MarcoBonelli 为什么?该算法使用大端字节序进行密钥处理。 - Grey
@Grey 哦,好的,或许应该在问题中明确说明。 - Marco Bonelli
1
请注意,使用联合体并不是一种非常便携的执行此类计算的方式。它高度依赖于实现。最好使用适当类型的变量(例如uint16_t)上的位运算符,而不是位域,如果您不希望在更改编译器或平台时出现任何意外情况! - th33lf
1
@th33lf 如果你不想有任何意外,最好使用位运算符... 不仅仅是更好,而且是完全和绝对必要的如果剩余空间不足,无法容纳的位域是放入下一个单元还是重叠相邻单元是实现定义的。位域在单元内的分配顺序(高位到低位或低位到高位)是实现定义的。可寻址存储单元的对齐方式是未指定的。 - Andrew Henle
显示剩余4条评论
3个回答

8
问题在于 union 表示每一个一位比特域成员都访问同一个比特位。您想要的是:
union lfsr{
    //... 
    struct {
        unsigned short ff_0 : 1;
        unsigned short ff_1 : 1;
        //... 
        unsigned short ff_f : 1;
    }flip_flops;

    unsigned short ff;
};

1
你想要做的是...除了位域完全不可移植之外,也没有任何一致且可移植的映射将任何位域映射到联合体的unsigned short ff成员的实际位上。 - Andrew Henle
2
这是不言而喻的,但至少它会在一些实现中起作用,而不是0。 - Antti Haapala -- Слава Україні

4
你可能对联合的理解有所不同。所有位域都在同一位置进行别名处理。你可能想要做这样的事情:
struct lfsr{
  //... 
  union{
    struct {
      unsigned short ff_0 : 1;
      unsigned short ff_1 : 1;
      //... 
      unsigned short ff_f : 1;
    };
    unsigned short ff;
  }flip_flops;
};

您可以在这里了解结构体和联合体之间的区别。
更新: 根据@the-busybee的评论,关于基于架构的位域对齐也值得注意,这涉及到代码在各种架构上的可移植性。 有关位端序讨论,请参阅此处的答案。

非常感谢,我以为联合体不能影响位域。 - Grey
1
请注意 ff 的字节序和位位置!它可能不是您所期望的。 - the busybee

3
当您声明Union时,Union的所有元素都是相同内存的一部分。它们只是以不同的方式访问。
 union{
        unsigned short ff_0 : 1;
        unsigned short ff_1 : 1;
        //... 
        unsigned short ff_f : 1;
        unsigned short ff;
    }flip_flops;

在这里,ff_0ff_1指向同一块内存,ff也是如此。所以当你给ff_0赋值时,ff_1也会自动赋相同的值。因此你观察到的是正确的。
你需要做的是,创建一个包含15位字段的结构体,并将union设置为结构体和无符号短整型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接