2009-05-26 13 views
9

長さが動的でなければならないインターネット経由でパケットを転送する必要があります。C:動的サイズの構造体に推奨されるスタイル

struct packet 
{ 
    int id; 
    int filename_len; 
    char filename[]; 
}; 

ゼロ長配列はISOに準拠していません。

代わりにchar filename[1];を使用しますか?しかし、sizeof(struct packet)は正しい値を返さなくなります。

答えて

6

古典的な問題。コンパイラが構造体のサイズを丸めればsizeof(foo)が1つ以上になることがあることに注意してください。これは次のようにすることができます:

struct packetheader { 
    int id; 
    int filename_len; 
}; 
struct packet { 
    struct packetheader h; 
    char filename[1]; 
}; 

これは迷惑です(h.idなどを使用する必要があります)が機能します。通常、私はそれを1つだけ扱っていますが、上記の方がわずかに移植性が高いかもしれません。

6

ここでは、動的サイズの構造の既存の例を見てください。私が知っている最良の例は、Win32のTOKEN APIです。彼らはただ1にレイモンド・チェンが、彼らはこのような失敗はsizeofなどの操作については

行われている理由を正確に詳述豊富なブログ記事をやったダウン解決マクロANYSIZE_ARRAYを使用しています。これは、動的にサイズ変更された構造体に対してどのようなソリューションを選択しても失敗します。 sizeofはコンパイル時の操作で、実行時に構造のサイズを変更します。単に働くことはできません。

+0

sizeofとは、ダイナミックフィールドではなく、ダイナミックフィールドのサイズを意味します。なぜなら、ダイナミックフィールドのサイズを含む構造体でUDPパケットを受け取った後、ダイナミックフィールドを読み込むためです。 – codymanix

4

char filename[1]を使用し、0バイトの終端を含めることをお勧めします。このように、あなたは正しい構造のサイズをmalloc()と、このような単発のエラーを回避することができます

ptr = malloc(sizeof(struct packet)+filename_len); 
strncpy(&ptr->filename, filename, filename_len); 

しかし、受信機は、それはfilename_len+1バイトを読み取るために必要があることを知っているために必要があります。

3

実際にzero-length arraysは標準の一部ではありません。しかし、あなたのコードスニペットには、ISO C99標準の一部である柔軟な配列があります。 C99を使用することが可能な場合は、フレキシブルな配列を使用してください.jesupの提案がおそらく最高です。

関連する問題