我正在为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,正如预期的那样。
我试图摆脱两个平台上所需属性的对齐,但我不知道我缺少什么¿为什么尺寸会根据平台而变化? ¿我正在使用正确的属性来控制对齐?
提前致谢。
答案 0 :(得分:4)
C ++标准没有指定如何精确布局位字段。许多编译器将为每个位字段组件使用常规整数,这意味着更快的处理但更大的结构,除非您指定了在Linux情况下所做的不同首选项。
有关VS2010使用的算法,请参阅here。
修改:您的代码存在问题。请记住,对于带符号的基类型,符号位将消耗位字段的一位。并且您的枚举(与大多数人一样)可能会被签名(无论是否,是实施定义的),因此当您在E_EXTENDED_COMMANDS
中存储mMessageType
并立即发现值时,您可能会看到意外不存在。
使用最近的编译器,您可以force the enums to be unsigned并避免此问题。