3


私は小道具に取り組む必要があります。バイナリファイル形式であり、構造体を使用してそれを実現したい。
構造体に定数バイトシーケンスが必要ですが、ATMではそれを実現する方法がわかりません。

私はそのようなことについて考えました:

#include <cstdint>
#pragma pack(push,1)

typedef struct PAYLOAD_INFO {
    const uint8_t magicnumber[4] =  { 0xFA, 0x11 , 0x28 , 0x33 };
    uint16_t UMID;
    const uint16_t VID = 1487 ;
    uint32_t crc;
};

#pragma pack(pop)

int main (){
  PAYLOAD_INFO pldInst;
  pldInst.UMID = 5;
  pldInst.crc = 0x34235a54;
  ...
  writeToFile(&PAYLOAD_INFO,sizeof(PAYLOAD_INFO));
}

最終的に、「pldInst」は、この例のバイト順序に関係なく、(メモリ内で)そのように見えるはずです。

0x00000000:  0xFA, 0x11 , 0x28 , 0x33
0x00000004:  0x00, 0x05 , 0x05 , 0xCF
0x00000008:  0x34, 0x23 , 0x5a , 0x54

私はすでに「デフォルト」アプローチを試しました。

#include <cstdint>
#pragma pack(push,1)

typedef struct PAYLOAD_INFO {
    static const uint8_t magicnumber[4];
    uint16_t UMID;
    static const uint16_t VID = 1487 ;
    uint32_t crc;
};

const uint8_t magicnumber[4] =  { 0xFA, 0x11 , 0x28 , 0x33 };

#pragma pack(pop)

しかし、意図したとおりには機能しません。

すべての構造体メンバーのメモリサイズを計算したり、新しいメモリを割り当てたり、すべてのメンバーをコピーしたりせずに、これを実行する方法はありますか?

g++4.6.3を使用しています。

よろしく、トーマス

更新:
@bikeshedderによって提供されるc ++ 11ソリューションは非常にうまく機能しますが、g++4.7以降でのみコンパイルされます。

4

2 に答える 2

4

現在、スタティックはグローバルスタティックを定義しているだけです。クラスの一部となる静的を定義するには、クラス指定子を追加する必要があります。

const uint8_t PAYLOAD_INFO::magicnumber[4] = { 0xFA, 0x11 , 0x28 , 0x33 };

とはいえ、@bikeshedderが以下で説明するように、統計はメモリに個別に保存されるため、構造体の新しいインスタンスを作成すると、そのインスタンスにはインスタンスのメモリ位置にマジックナンバーが含まれないため、の使用はあなたのwriteToFileようには機能しません予想。

于 2013-02-02T02:16:01.563 に答える
3

structs同じマシンでの実行が保証され、そのように使用されることが想定されているカーネルインターフェイスを使用している場合を除き、rawメモリへのキャストは一切行わないことをお勧めします。

これは移植性がなく(エンディアンの問題)、コンパイラーごとに少し異なり、パフォーマンスはそれほど良くありません。全体として、それはこの悪い慣行を正当化するものではありません。

コード例が機能しない理由は、静的メンバーです。静的メンバーはオブジェクト(クラスではなく)の一部ではなく、UMIDそのcrcように記述されているためです。

struct PAYLOAD_INFO {
    const uint8_t magicnumber[4] = { 0xFA, 0x11, 0x28, 0x33 };
    uint16_t UMID;
    const uint16_t VID = 1487 ;
    uint32_t crc;
};

このコードはC++11でのみ機能しますが、含めるので、cstdintすでにそのC++バージョンを使用していると思います。C ++ 11を使用しない場合は、コンストラクターでメンバーを初期化する必要がありますconst。また、マジックナンバーは初期化できないため、使用しないでください。(参照:C ++のクラス初期化子でconst配列を初期化する

struct PAYLOAD_INFO {
    const uint8_t magicnumber[4] = { 0xFA, 0x11, 0x28, 0x33 };
    uint16_t UMID;
    const uint16_t VID = 1487 ;
    uint32_t crc;
};

C ++ 98の場合、次のことを行う必要があります。

struct PAYLOAD_INFO {
    uint8_t magicnumber[4];
    uint16_t UMID;
    const uint16_t VID;
    uint32_t crc;
    PAYLOAD_INFO() : VID(1487)
    {
        magicnumber[0] = 0xFA;
        magicnumber[1] = 0x11;
        magicnumber[2] = 0x28;
        magicnumber[3] = 0x33;
    }
};
于 2013-02-02T02:20:46.743 に答える