【问题标题】:Why is the enum incompatible with bit fields in Windows?为什么枚举与 Windows 中的位域不兼容?
【发布时间】:2012-05-25 09:38:07
【问题描述】:

我正在为 Windows 和 Linux 开发 EBDS 协议接口。我正在尝试将协议所需的所有数据打包到结构中,然后将结构本身和所有其他内容写入串行端口,将其发送到设备。

协议的第一部分是数据打包,其中一个部分是符合这个描述的控制字节:

Bit 0: Acknowledgement bit (switchs between 0 and 1 in each send).
Bit 1 to 3: Device Type.
Bit 4 to 6: Message Type.
Bit 7: Unused.

为了处理 tis 控制字节,我创建了两个枚举和一个结构:

enum E_DEVICE_TYPE
{
    E_BILL_ACCEPTOR_WITH_SINGLE_ESCROW = 0x0, // 000
    E_RESERVED_1 = 0x1, // 001
    E_RESERVED_2 = 0x2, // 010
    E_RESERVED_3 = 0x3, // 011
    E_RESERVED_4 = 0x4, // 100
    E_RESERVED_5 = 0x5, // 101
    E_RESERVED_6 = 0x6, // 110
    E_RESERVED_7 = 0x7,
};

enum E_MESSAGE_TYPE
{
    E_RESERVED = 0x0,
    E_STANDARD_OMNIBUS_COMMAND = 0x1,
    E_NOT_USED = 0x2,
    E_OMNIBUS_WITH_BOOKMARK_MODE = 0x3,
    E_CALIBRATE_REQUEST = 0x4,
    E_FIRMWARE_DOWNLOAD_REQUEST = 0x5,
    E_AUXILIARY_COMMAND_REQUEST = 0x6,
    E_EXTENDED_COMMANDS = 0x7,
};

#ifndef LINUX
#pragma pack(1)
#endif
struct sControlByte
{
    sControlByte(bool aAcknowledgeFlag, E_DEVICE_TYPE aDeviceType, E_MESSAGE_TYPE aMessageType);

    const bool mACK : 1;
    const E_DEVICE_TYPE mDevice : 3;
    const E_MESSAGE_TYPE mMessageType : 3;
    const bool mUnused : 1;
#ifdef LINUX
}__attribute__((packed));
#else
};
#endif

当我询问 sControlByte 结构的大小时,在 Windows 编译 (Visual Studio 2010) 上该值等于 6,但在 Linux(使用 gcc 4.2.3)上,该结构的大小为 1,正如预期的那样。

我试图摆脱两个平台上所需属性的对齐,但我不知道我缺少什么 ¿为什么大小会根据平台而变化? ¿ 我使用正确的属性来控制对齐方式?

提前致谢。

【问题讨论】:

  • VS 编译器也有 pack() pragma,所以你不需要 ifndef 它。
  • @Dmitry ifndef LINUX only 允许 MSVC 使用 pack(),所以你绝对需要它。
  • @harper 你说得对,我忽略了它。

标签: c++ enums bit-fields


【解决方案1】:

C++ 标准没有指定位域的精确布局。许多编译器将为每个位字段组件使用常规整数,这意味着更快的处理但更大的结构,除非您指定不同的偏好,就像在 Linux 的情况下所做的那样。

请参阅here 了解 VS2010 使用的算法。

编辑:您的代码有问题。请记住,对于带符号的基本类型,位字段的一位将被符号位消耗。并且您的枚举(像大多数人一样)可能已签名(无论它们是否是实现定义的),因此当您将 E_EXTENDED_COMMANDS 存储在 mMessageType 并立即发现 该值不存在时,您可能会看到惊喜。

使用最近的编译器,您可以force the enums to be unsigned 并避免此问题。

【讨论】:

  • 很好奇,我认为由于涉及到位字段,因此该字段的基本类型对于代码中的使用而不是大小的使用无关紧要。
  • @PaperBirdMaster - 这是真的。然而,当位域的组件没有被打包时,访问它们通常会更快,因为这样就没有必要在代码生成级别上对相邻的域进行各种移位和屏蔽。顺便说一句,我刚刚注意到您的结构在某些平台上可能根本不起作用,请参阅对答案的编辑。
猜你喜欢
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
相关资源
最近更新 更多