1

私はWindowsとLinux用のEBDSプロトコルインターフェースに取り組んでいます。プロトコルに必要なすべてのデータを構造体にパックしようとしています。次に、構造体自体と他のすべてのものをシリアルポートに書き込んで、デバイスに送信します。

プロトコルの最初の部分はデータパッケージングであり、パッケージの部分の1つはこの説明に一致するコントロールバイトです。

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.

制御バイトを処理するために、2つの列挙型と1つの構造体を作成しました。

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です。

両方のプラットフォームで必要な属性との配置を削除しようとしましたが、何が欠けているのかわかりません¿プラットフォームによってサイズが変わるのはなぜですか?¿私は正しい属性を使用して配置を制御していますか?

前もって感謝します。

4

1 に答える 1

4

C ++標準では、ビットフィールドの正確な配置方法は指定されていません。多くのコンパイラは、ビットフィールドコンポーネントごとに通常の整数を使用します。これは、Linuxの場合に行った別の設定を指定しない限り、処理は高速ですが構造体が大きくなることを意味します。

VS2010が使用するアルゴリズムについては、こちらをご覧ください。

編集:コードに問題があります。符号付きベースタイプでは、ビットフィールドの1ビットが符号ビットによって消費されることに注意してください。また、列挙型(ほとんどの人の列挙型と同様)は署名されている可能性があり(実装定義されているかどうかに関係なく)、格納E_EXTENDED_COMMANDSmMessageTypeてすぐに値がないことに気付くと驚きが生じる可能性があります。

最近のコンパイラでは、列挙型を強制的に符号なしにして、この問題を回避できます。

于 2012-05-25T09:45:21.127 に答える