2011-04-24 37 views
1

私はlinuxでプログラミングしています。これは私にとって初めてのことです。私は、「レイヤー7」ネットワークプロトコルを設計するプロジェクトに取り組んでいます。これらのパケットにはリソースが含まれています。また、リソースの種類によっては、そのリソースの長さが異なります。私はC/C++にはまったく新しいものですが、私はすべてのことをよく理解しています。アイデアは、私が "一般的なリソース"型を作ることができ、それがどんなリソースであったかに応じて、このtypedef構造体へのポインタとしてvoid *をキャストして、それは "キャスティング"の世話をするだろう。とにかく、ここに私が思いついたものがあります:(C/C++)構造体を含む共用体を含む構造体...?

typedef struct _pktresource 
{ 
    unsigned char Type; // The type of the resource. 

    union { 
     struct { // This is used for variable length data. 
      unsigned short Size; 
      void *Data; 
     }; 

     void *ResourceData; // Just a generic pointer to the data. 
     unsigned char Byte; 
     char SByte; 
     short Int16; 
     unsigned short UInt16; 
     int Int32; 
     unsigned int UInt32; 
     long long Int64; 
     unsigned long long UInt64; 
     float Float; 
     double Double; 
     unsigned int Time; 
    }; 
} pktresource, *ppktresource; 

これの背後にある原理は単純でした。しかし、私が何かをするとき

pktresource.Size = XXXX 

それは1バイトの代わりに構造体に4バイトを開始します。私はここで大きなコンセプトを理解していませんか?それは私のように感じるので。

編集:私はになってそのような冒頭で

pktresource.Type 

それが起動などを参照する場合は、言及を忘れていました。

EDIT:正しい整列のためにプラグマステートメントを追加しました。修正後は、コードは次のようになります。

#pragma pack(push) 
#pragma pack(1) 

typedef struct _pktresource 
{ 
    unsigned char Type; // The type of the resource. 

    union { 
     struct { // This is used for variable length data. 
      unsigned short Size; 
      unsigned char Data[]; 
     }; 

     unsigned char ResourceData[]; // Just a generic pointer to the data. 
     unsigned char Byte; 
     char SByte; 
     short Int16; 
     unsigned short UInt16; 
     int Int32; 
     unsigned int UInt32; 
     long long Int64; 
     unsigned long long UInt64; 
     float Float; 
     double Double; 
     unsigned int Time; 
    }; 
} pktresource, *ppktresource; 

#pragma pack(pop) 
+3

"私はLinuxでプログラミングしています。これは私にとって初めてのことです。"、 "私はC/C++の新機能です。" - ネットワークプロトコルを作成していますか? –

+0

私はネットワーキング、プログラミング、またはLinux自体に新しいものではありません。私はWindows上で1つの言語または別の言語で約13年間プログラミングしています。あなたは私の質問に対する答えを知っていますか、それとも真実ではないと言いましたか? –

+0

"私はWindows上で1つの言語または別の言語で約13年間プログラミングしていますが、まだC/C++を初めて使用しています。どの言語を使用していましたか? –

答えて

2

私はここに主要な概念を把握することができないのですか?

あなたはstructure alignmentの知識が不足しています。基本的には、特定のフィールドをサイズに応じて> 1バイト境界でアライメントするよう強制します。 #pragmaを使用してこの動作を無効にすることはできますが、構造がアプリケーション外のどこでも使用されている場合、相互運用性の問題を引き起こす可能性があります。

+0

オハイオ州の男、私は以前に "構造の整列"という言葉を聞いたことがあるが、それが何であるかを知らなかった。この構造体は、アプリケーション内でのみネットワークデータを解析するために使用されます。 –

+0

それで問題はありません。あなたの 'void * Data'メンバ(ポインタ型)の長さは4バイトで、4バイトの境界に整列しています。それが最大のユニオンメンバーなので、ユニオン全体がそのサイズになり、その境界に整列されます。バイト2ではなくバイト5から開始されます。 –

+0

#pragmaを使用すると、メモリの取得がワード境界で分割されたデータを処理する必要があるため、処理が遅くなる可能性があります。スペースが考慮されない限り、私はコンパイラのデフォルトレイアウトを混乱させるとは思わない。 (あなたはTypeを構造体の一番下に移動することもできます) –

2

私は問題が整列だと思います。デフォルトでは、ほとんどのコンパイラはマシン/ OSのワードサイズ、この場合32ビット/ 4バイトに整列します。したがって、unsigned char型のフィールドが先頭にあるので、コンパイラはSizeフィールドを次の偶数の4バイトの境界にプッシュします。

は先にあなた構造定義の

#pragma pack 1 

を試してみてください。

私はどのコンパイラを使用しているのかわかりませんが、StackOverflowのこれらの失礼な子供のほとんどが生まれる前から、ネットワークプログラミングで定期的に使用されていた古き良きCコードです。

+0

私はgccを使用しています4.4.3 –

+0

wikiの記事を読んだ後で、たくさんありがとう、私は1アップですが、十分な担当者はいません。 –

関連する問題