【问题标题】:Using bit fields in struct and reading an instance from Memory with C++在结构中使用位字段并使用 C++ 从内存中读取实例
【发布时间】:2026-02-17 20:15:02
【问题描述】:
unsigned __int16 var16bit= 6545; //00011001 10010001
unsigned __int8 var8bit;
memcpy(&var8bit, &var16bit, sizeof(var8bit));
cout << var8bit; // result is 145 which is 10010001

在使用小端机器时,首先将 lsb 写入内存,然后在必要时将偏移量添加到地址。在此示例中,一个 16 位整数被复制到 8 位整数,并且由于目标空间不足而丢失了它的 msb 端。反向行为发生在大端机器中。

下面还有一个例子

这是我的结构

struct Account 
{
   unsigned int dollar : 4;
   unsigned int euro : 4;
   unsigned int pound : 4;
   unsigned int ruble : 4;
};

int _tmain(int argc, _TCHAR* argv[])
{
    Account myWealthyAccount = {};
    myWealthyAccount.dollar = 2; // 0010
    myWealthyAccount.euro = 3; // 0011
    myWealthyAccount.pound = 4; // 0100
    myWealthyAccount.ruble = 5; // 0101

    unsigned __int16 sum;
    memcpy(&sum, &myWealthyAccount, sizeof(myWealthyAccount));
    cout << sum;
    // result is 0101010000110010  ruble pound euro dollar
    unsigned __int8 sum8Bit;
    memcpy(&sum8Bit, &myWealthyAccount, sizeof(sum8Bit));
    cout << sum8Bit; // result is 50 which is 0011 0010 euro dollar

    return 0;
}

0101010000110010 卢布英镑欧元美元

为什么它以卢布英镑欧元美元的形式订购,为什么不相反?

为什么卢布在msb旁边,美元在lsb旁边?

这是关于小端还是大端机器?或者这是关于结构的?这是关于编译器的吗?

如果我在大端机器上运行这个例子,会发生什么结果?为什么?

我愿意接受有关该主题的所有建议,例如文章、视频、网站。

谢谢

【问题讨论】:

  • 为什么你认为你需要使用位域?这几乎总是一个错误。
  • @NeilButterworth 你能假设我正在使用它吗?关于“为什么这是一个如此错误”的解释也很好。
  • 好吧,我建议不要使用它,因为代码会很慢并且(取决于具体情况)可能会比不使用它占用更多的内存,而且它赢了不便携。使用位域必须有一个非常积极的理由,而且这样的理由并不多。
  • struct 中打包位域的顺序是实现定义的,可能与字节序或编译器编写者的心情有关。永远不要依赖位域排序。
  • 但是,我不会立即说没有人应该使用位域——有时使用位域是合理的(例如,通过使数据更小,它们可以改善局部性)。你在轮班中失去的东西,你会在记忆中的旅程中节省下来。

标签: c++ struct endianness bit-fields


【解决方案1】:

“为什么它以卢布英镑欧元美元的形式订购,为什么不相反?”

我复制了您的代码并得到了完全相同的结果。 在您的第一个示例中,16 位整数的存储方式为 00011001 10010001。因此,如果您只取 lsb,您将得到 10010001。但您的位域存储方式为 0101 0100 0011 0010。

如果您查看注释下的http://en.cppreference.com/w/cpp/language/bit_field“此外,在某些平台上,位字段从左到右打包,在其他平台上从右到左打包”。所以它是由实现定义的,你有什么顺序。

【讨论】: