5

次のプログラム出力は常に111です。「c++オブジェクトモデルの内部」の本では、オフセットが与えられると述べられています。目的は、オブジェクトのレイアウトを見つけることでもあります。しかし、私は出力と混同しています。使用済みg++4.5.2

class Test
{
    public:
        float a;
        float b;
        float c;
};

int main()
{
    float Test::*ptr = &Test::a;
    float Test::*ptr1 = &Test::b;
    float Test::*ptr2 = &Test::c;
    cout<<ptr<<endl;
    cout<<ptr1<<endl;
    cout<<ptr2<<endl;

    return 0;
}

出力:

1
1
1

編集(フォローアップ質問):この本では、originがPoint3dのオブジェクトであり、yがクラスPoint3dのメンバー変数である場所origin.y = 0に変換できることが記載されています。&origin + (Point3d::y-1)コンパイルするとコンパイルエラーが発生しましたが。

4

2 に答える 2

5

あなたはメモリオフセットを見つけたいと書いていました。FredOverflow が書いていることは完全に真実ですが、 、およびTestのアドレスを知りたい場合は、クラスのインスタンスを作成する必要があります。例えば:abc

Test t;
float *ptr = &t.a;
float *ptr1 = &t.b;
float *ptr2 = &t.c;

私のマシンでは、これにより次の 3 つのアドレスが生成されます。

0x7fff564f8918
0x7fff564f891c
0x7fff564f8920

そして、それらが 4 バイト (またはsizeof(float)) 離れており、a のサイズTestが 12 バイト ( を使用sizeof(Test)) であることがわかります。なお、 のアドレスは のアドレスと&t同じ0x7fff564f8918です&t.a。これが、クラスのインスタンスのメモリ レイアウトTestが形成される方法です。

PODを使用して、型のメンバーのオフセットを見つけることもできますoffsetof()

cout << offsetof(Test, a) << endl;
cout << offsetof(Test, b) << endl;
cout << offsetof(Test, c) << endl;

収量

0
4
8

offsetof(Test, b)本質的に同じであることに注意してください

(unsigned long long) &(((Test*) 0)->b) - (unsigned long long) (Test*) 0

フォローアップの質問への回答:

前述と同じエラーのため、そのコードは機能しません。yただし、メンバーのアドレスを計算しoriginて値を割り当てたい場合は、次の0ように実行できます。

class Point3d {
public:
  float x, y, z;
};

Point3d origin;
origin.y = 10;

// We take the address of origin, which points to the first member, 
// then add the offset to the member y.
float *ptr = (float*) ((unsigned long long) &origin + offsetof(Point3d, y));
cout <<  "Old value: " << *ptr << endl;
*ptr = 0;
cout <<  "New value: " << *ptr << endl;

次の出力が得られます。

Old value: 10
New value: 0

Point3dこれはが型であるためにのみ可能であることをもう一度思い出してPODください。

于 2012-08-19T19:22:41.923 に答える