11

次の構造体を検討してください。

struct Vector4D
{
   union
   {
      double components[4];
      struct { double x, y, z, t; } Endpoint;
   };
};

WinApi の IPAddress 構造体で似たようなものを見たように思えます。アイデアは、配列コンポーネントをインデックスと名前の両方で使用できるようにすることです。次に例を示します。

Vector4D v;
v.components[2] = 3.0;
ASSERT(v.Endpoint.z == 3.0) //let's ignore precision issues for now

C++ 標準では、POD 構造体の先頭に「空の」スペースがないことが保証されています。つまり、要素 x は Endpoint 構造体の先頭に配置されます。これまでのところ良い。xしかし、 and y、またはyandなどの間に空のスペースやパディングがないという保証はないようですz。ただし、C99標準はチェックアウトしていません。

問題は、Endpoint 構造要素間に空のスペースがある場合、アイデアが機能しないことです。

質問:

  1. これが C または C++ のいずれかで機能するという保証はないというのは正しいですか。

  2. これは、既知の実装で実際に機能しますか? つまり、これが機能しない実装を知っていますか?

  3. 同じ考えを表現するための標準的な(コンパイラ固有ではない)方法はありますか?C++0x のアライメント機能が役立つのではないでしょうか?

ところで、これは私が製品コードで行っていることではありません。心配しないでください。前もって感謝します。

4

4 に答える 4

5
  1. はい
  2. アーキテクチャとコンパイラ戦略のアライメントの必要性に依存します
  3. いいえ、ただし、オブジェクト ラッパーを作成することはできます (ただし、最終的には.z()ではなく になります.z)

ほとんどのコンパイラは、プラグマまたは属性を使用した構造のスカッシュをサポートする必要があります。#pragma pack例えば。

于 2011-06-23T10:20:50.253 に答える
4

クラス内の参照の前に配列を宣言して、それらが有効なデータを指していることを確認する限り、配列の各要素への参照を使用することで、メモリ アライメントの問題を回避できます。アライメントが double の問題になるとは思えませんが、他のタイプの問題になる可能性があります (おそらく 64 ビット Arch でのフロート?)

#include <iostream>
using namespace std;

struct Vector4D
{
    Vector4D() : components(), x(components[0]), y(components[1]), z(components[2]), t(components[3]) { }

    double components[4];

    double& x;
    double& y;
    double& z;
    double& t;
};

int main()
{
    Vector4D v;

    v.components[0] = 3.0;
    v.components[1] = 1.0;
    v.components[2] = 4.0;
    v.components[3] = 15.0;

    cout << v.x << endl;
    cout << v.y << endl;
    cout << v.z << endl;
    cout << v.t << endl;
}

お役に立てれば。

于 2011-06-23T10:58:34.863 に答える
2

標準に関しては、次の 2 つの問題があります。

  • ユニオン内の要素に書き込み、別の要素から読み取るときに何が起こるかは規定されていません。C 標準 6.2.6.1 および K.1 を参照してください。
  • 標準では、構造体のレイアウトが配列のレイアウトと一致することは保証されていません。詳細については、C 標準 6.7.2.1.10 を参照してください。

そうは言っても、実際にはこれは通常のコンパイラで機能します。実際、この種のコードは広く普及しており、ある型の値を別の型の値に再解釈するためによく使用されます。

于 2011-06-23T11:50:32.173 に答える
0

すべての変数が type であるため、バイトをパディングしても問題は発生しませんdouble。コンパイラは配列Vector4Dとして扱います。doubleつまり、v.Endpoint.zは本質的に と同じv[2]です。

于 2011-06-23T10:33:28.060 に答える