【问题标题】:Bitwise structure programming in CC中的按位结构编程
【发布时间】:2013-11-07 07:13:10
【问题描述】:

这是如何工作的?

struct {
    int a : 21;
    int b : 11;
};

a 和 b 是两个独立的 int 变量还是使用不同位域的同一个变量?

【问题讨论】:

    标签: c bit-fields


    【解决方案1】:

    这是struct 中的两个独立变量,一个名为a,一个名为b。但是,它们的大小使得 a 应该有 21 位,b 应该有 11 位。访问一个变量并对其进行操作不会影响另一个变量。

    希望这会有所帮助!

    【讨论】:

    • 谢谢。所以本质上两者都是 32 位整数,但只使用了 21 位 a 和 11 位 b 用于保持其他位未使用?或者编译器是否以某种方式对此进行了优化?人们可能更喜欢使用一个 32 位变量并将其拆分为 21:11 位字段...
    • @AbhinavChoudhury:是的,其他位将不会使用。即使没有位字段也会发生同样的事情,请考虑声明 struct s { int x; char y; };,它在大多数系统上使用 8 个字节。
    • @AbhinavChoudhury 它们是 2 个“32 位”(或 16 位,取决于平台)整数,这仅仅是因为系统处理内存的方式。如果你声明 int a:5,CPU 也会存储这个变量是 32 位的(根据系统可能是 16 位),因为它是一个整数并且整数在内存中占用一定的大小(再次依赖于平台,取决于我的system 和 int 的大小为 2 字节,但您的情况不一定如此)。在您的情况下,:21:11 只是限制了您可以分配给此变量的最大值。
    • 顺便说一句。如果你想将它们存储在同一个 32 位寄存器中,你可以这样做(考虑到 int 是 4 字节长的事实):int ab=a<<11+b.
    • @DietrichEpp:您基于什么断言将使用两个 32 位实体,而多余的位未使用,而不是将 ab 打包到一个 32 位实体中? C 标准要求将连续字段打包到实现使用的任何单元中,如果它们完全适合的话。 (如果它们不适合,则标准允许将一个字段部分打包在一个单元中,部分打包在下一个单元中,或者保留未使用的位。)
    【解决方案2】:

    这里的“变量”是什么意思并不完全清楚。如果您的意思是可以获取地址的内存,那么位域不符合描述,因为它们是“可寻址存储单元”的一部分。如果“变量”是指“我可以在其中存储一些值的位集”,那么 a 和 b 看起来就像结构中的任何其他字段。

    不过,足够的语义吹毛求疵了。让我们去源头:

    C99 standard 中的 ch 6.7.2.1 说:

    10 一个实现可以分配任何大的可寻址存储单元 足以容纳一个位域。如果有足够的空间,一个位域 紧跟在结构中的另一个位域之后应打包 到同一单元的相邻位。如果剩余空间不足, 是否将不适合的位域放入下一个单元或 重叠相邻单元是实现定义的。的顺序 一个单元内的位域分配(高阶到低阶或 低阶到高阶)是实现定义的。对齐方式 可寻址存储单元未指定。

    因此,根据编译器选择的“可寻址存储单元”,您的 a 和 b 可能最终位于不同的“存储单元”中,具体取决于编译器的具体情况。

    【讨论】:

    • 有点迂腐,C 标准中的内容是“条款”,而不是“章节”(关于您的缩写“ch”)。
    【解决方案3】:

    它的实现方式取决于系统架构。如果你举一个更直接的例子:

    struct x {
      uint8_t a : 2;
      uint8_t b : 3;
    };
    

    这里ab 可能会共享相同的内存字节,例如:xxxb bbaa(其中 x 未使用)。

    我相信对齐和打包的语义是未定义的 - 最好尝试一下!如果您正在做一个多平台项目,请注意不同的硬件(甚至可能是编译器)。

    struct x s;
    s.a = 3;
    s.b = 5;
    printf("0x%02X\n", *((char*)&s) );
    

    输出可能是0x030x050x16 甚至0x25

    我希望看到0x16...

    在我看来,在传输位域时,您应该始终手动构建已知状态。

    uint8_t buf[];
    buf[x] = 0;
    buf[x] |= (s.a) & 0x03;
    buf[x] |= (s.b << 2) & 0x1C;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      相关资源
      最近更新 更多