2009-06-18 5 views
0

構造体の特定のメンバーのサイズを取得します。C:sizeof(((SomeStruct *)0) - > some_member)を行う良い方法は?

sizeof(((SomeStruct *) 0)->some_member)私のために働くが、それを行うにはより良い方法があるように感じる。

私は#define SIZEOF_ELEM(STRUCT, ELEM) sizeof(((STRUCT *) 0)->ELEM)でしたし、SIZEOF_ELEM(SomeStruct, some_member)を使用しても構いませんが、すでに組み込みの方が良いかどうか疑問です。

私の具体的な使用例はhsc2hs(Haskell Cバインディング)です。

pokeArray (plusPtr context (#offset AVFormatContext, filename)) . 
    take (#size ((AVFormatContext *) 0)->filename) . 
    (++ repeat '\NUL') $ filename 
+2

このアプローチには何が問題なのですか?十分にいいですね。標準のoffsetof()マクロも同じように動作します。 – qrdl

+3

Cでは、酷いように見えますが、しばしば正しいです;) –

答えて

5

逆参照する変数があることを保証できない場合、取得したものと同じくらいクリーンです。 (可能であれば、sizeof(var.member)またはsizeof(ptr->member)だけを使用してください。ただし、コンパイル時定数が必要な状況では動作しません)。

長い時間(1990年頃)私はベースアドレス0を使って 'offsetof'が定義されたコンパイラを実行し、クラッシュしました。 をハッキングして0の代わりに1024を使うようにして問題を解決しましたが、今はそのような問題に遭遇するべきではありません。

3

あなたはすでに正しい解決策を得ていると思います。あなたはstddef.hを掘り下げて、offsetofがどのように定義されているかを調べることができます。なぜなら、これは非常によく似ているからです。

メンバのサイズと、メンバのオフセットと次のメンバのオフセットとの差が、パディングによって十分に異なることを覚えておいてください。

3

C++ではsizeof(SomeStruct :: some_member)を実行できますが、これはcでスコープ解決演算子はありません。あなたが書いたものは、私が知る限り、書くことができるほど良いものです。

2

マイクロソフトは、そのヘッダーの1つに、次のようにあります。

#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field)) 

私は何が違うのを行うには理由を見ません。

彼らはのためのマクロが関連している:

RTL_SIZEOF_THROUGH_FIELD() 
RTL_CONTAINS_FIELD() 

と気の利いた:そのリンクフィールドは、構造体の開始時にも必要とすることなく、まっすぐCでの一般的なリストを実装するのに役立ちます

CONTAINING_RECORD() 

。詳細はKernel Mustard articleを参照してください。