c++ - 为什么枚举与 Windows 中的位字段不兼容?

标签 c++ enums bit-fields

我正在研究适用于 Windows 和 Linux 的 EBDS 协议(protocol)接口(interface)。我试图将协议(protocol)所需的所有数据打包到结构中,然后将结构本身和所有其他内容写入串行端口,将其发送到设备。

协议(protocol)的第一部分是数据封装,封装的一部分是与此描述相匹配的控制字节:

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.

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

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。

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

提前致谢。

最佳答案

C++ 标准没有指定位字段的确切布局方式。许多编译器将对每个位域组件使用常规整数,这意味着处理速度更快但结构更大,除非您指定不同的首选项,就像您在 Linux 中所做的那样。

参见 here对于 VS2010 使用的算法。

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

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

关于c++ - 为什么枚举与 Windows 中的位字段不兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10752002/

相关文章:

c++ - 字段并集和结构并集之间的区别

c++ - Boost 在重载新/删除运算符时导致无效 block

enums - 在 Swift 中声明和使用位域枚举

c++ - C++ 中直线与线段的交点

c# Android 如何将 Enum 放入 bundle

postgresql - 有没有办法在 postgresql 中备份数据+用户定义的枚举?

c++ - 多值 DWORD 枚举作为一个函数参数 C++

java - 在给定的 int 中设置位 1-3,仅根据需要设置位 1-3

c++ - std::tuple 参数中的类型顺序有什么影响吗?

c++ - 在无向树中寻找路径的算法