構造体のメンバーの構造体の開始に対するオフセットをどのように知るか


#include <stdio.h>
#define STRUCT_OFFSET(stru_name, element) (unsigned long)&((struct stru_name*)0)->element
struct stru_addr
{
    int a;
    char b;
    int d;
    char c;

};

int main(void)
{
    struct stru_addr s;
    printf("start addr of s = %x
"
, &s.a);
    
    unsigned long offset = STRUCT_OFFSET(stru_addr, c);// c


    printf("c_addr = %x, offset = %u
"
, &s.c, offset);
    printf("start addr of s caculated from c addr: %x
"
, (char *)&s.- offset);//
    return 0;
}

実は、プログラム全体の最も重要な部分は、構造体のメンバーの構造体ヘッダアドレスに対するオフセット量をどのように求めるかです.ここでの解決策は、仮想アドレス0が存在すると仮定し、このアドレスを強制的に構造体ポインタタイプ(struct stru_name*)0に変換することである.アドレス0がsizeof(struct)-1の長さのメモリ領域に開始されると、1つの構造体のメモリと見なすことができる.このように、構造体の任意の要素は、構造体ポインタを参照解除することによって得ることができる.この構造体の開始アドレスは0であるため、任意のメンバーのアドレスは、構造体の開始アドレスに対するオフセットに等しくなければならない.これは、オフセット量を計算する方法である:(unsigned long)&(struct stru_name*)0)->element.
上記のプログラムの結果は次のとおりです.


start addr of s = bfad7ac0c_addr=bfad 7 acc,offset=12 start addr of s caculated from c addr:bfad 7 ac 0上記の結果では,構造体内の整列問題も同時に考慮した.