4

構造体があります

typedef struct _pack_t {
    char tag[4];     
    int type;                
    size_t size;              
    size_t offset;           
    char data[0];           
} __attribute__((packed)) pack_t;

そして定義があります

#define PACK_OFFSET ((size_t)((pack_t *)0)->data)

とはどういう意味ですか? そして、ポインタ「0」を理解する方法は?

4

4 に答える 4

4

これはプリプロセッサ マクロです。構造体のdataメンバーのオフセットを生成します。pack_t囲んでいる構造体のベースアドレスがゼロの場合、このメンバーの絶対アドレスを取得することによってこれを行います。

NULL 以外のポインターを使用すると、型の任意の変数を宣言してpack_tから、構造体のアドレスとメンバーのアドレスの差をバイト単位で取得することで、次のように行うことができます。

pack_t dummy;
size_t offset = (char *)&dummy.data - (char *)&dummy;

(しかし、減算された 2 つのポインターが同じ配列の要素を指していないため、これは無効であるだけでなく、さまざまな理由で不要な余分なローカル変数も必要です。そのため、これはヌル ポインター)。

&( addressof ( ) 演算子を見なくても混乱しないでくださいdata。これは配列型であるため、最初の要素へのポインターに崩壊します。)

于 2013-03-29T10:01:02.167 に答える
3

これは、フィールド データのオフセットstruct _pack_tです。 (pack_t *) 0pack_t 型の NULL ポインタです。フィールド データの長さは 0 であることに注意してください。これは「変数」を意味します。何らかの関数によって埋められる必要があります。

元:memcpy((char *) packet + PACK_OFFSET, data, data_len);

于 2013-03-29T10:01:35.833 に答える
1

私はあなたの質問に答えているわけではなく、H2CO3 の意見をサポートするための例を示しているだけです。構造体のメンバーのオフセットを正しく取得するには、0 ポインターでなければなりません。コードは次のとおりです。

typedef struct _pack_t {
    char tag[4];     
    int type;                
    size_t size;              
    size_t offset;           
    char data[0];           
}pack_t;

#define OFFSET_0 ((size_t)((pack_t *) 0)->data)
#define OFFSET_1 ((size_t)((pack_t *) 1)->data)
#define OFFSET_2 ((size_t)((pack_t *) 2)->data)

int main(void){

    printf("%lu\n", OFFSET_0);
    printf("%lu\n", OFFSET_1);
    printf("%lu\n", OFFSET_2);
    return 0;
}

出力:

24
25
26
于 2013-03-29T10:17:05.133 に答える
1

黒板を想像してみましょう

先生はどこを見ても

PACK_OFFSET

(s)彼はボードのゴムを取り出してこすり洗いしPACK_OFFSET、それを交換します。

((size_t)((pack_t *)0)->data)
于 2013-03-29T10:04:22.040 に答える