4

インデックス付きフィールドではなく名前付きフィールドが必要ですが、一部の使用法では、フィールドを反復処理する必要があります。ばかげた単純化された例:

struct named_states {float speed; float position;};

#define NSTATES (sizeof(struct named_states)/sizeof(float))
union named_or_indexed_states {
   struct named_states named;
   float indexed[NSTATES];
}
...
union named_or_indexed_states states,derivatives;
states.named.speed = 0;
states.named.position = 0;
...
derivatives.named.speed = acceleration;
derivatives.named.position= states.named.speed;
...
/* This code is in a generic library (consider nstates=NSTATES) */
for(i=0;i<nstates;i++)
    states.indexed[i] += time_step*derivatives.indexed[i];

これにより、名前付き構造体からインデックス付き配列へのコピー、およびその逆のコピーが回避され、一般的なソリューションに置き換えられるため、保守が容易になります(状態ベクトルを拡張するときに変更する場所がほとんどありません)。私がテストしたコンパイラ(gcc / g ++とMSVCのいくつかのバージョン)。

しかし、理論的には、私が理解しているように、名前付きフィールドを作成してからインデックス付きフィールドを読み取るため、適切なユニオンの使用法に厳密に準拠していません。同じ構造体フィールドを共有しているとは言えません...

それが理論的に悪い(ポータブルではない)ことを確認できますか?

キャスト、memcpy()、または他のものを使用する方がよいでしょうか?

理論とは別に、実用的なPOVから、実際の移植性の問題(互換性のないコンパイラ、エキゾチックな構造アライメント、計画された進化など)はありますか?

編集:あなたの答えは、私の意図についてもう少し明確にする価値があります:

  • プログラマーがドメイン固有の方程式に集中し、変換関数のメンテナンスからそれらを解放できるようにするため(より堅牢ではないように見えるキャストやmemcpyのトリックを除いて、一般的な方程式を書く方法がわかりません)
  • 構造体(コンパイラーによって完全に制御される)と配列(プログラマーのミスが増える可能性のあるデクラレーションとアクセス)を使用して、コーディングのセキュリティをもう少し追加する
  • enumまたは#defineで名前空間を過度に汚染しないようにする

私は知る必要がある

  • 移植性/危険性が標準から外れていること(おそらく、積極的なインライン化を備えたコンパイラは、フルレジスタソリューションを使用し、メモリ交換がトリックを台無しにすることを回避します)、
  • そして、上記の懸念に部分的または全体的に対処する標準的な解決策を見逃した場合。
4

3 に答える 3

3

named_statesの2つのフィールドが配列要素と同じように並んでいる必要はありません。彼らがそうする可能性は十分にありますが、そこにはコンパイラの依存関係があります。

これがあなたがやろうとしていることのC++での簡単な実装です:

struct named_or_indexed_states {
    named_or_indexed_states() : speed(indexed[0], position(indexed[1]) { }
    float &speed;
    float &position;
    float indexed[2];
};

参照要素が原因でサイズが大きくなる場合は、アクセサを使用してください。

struct named_or_indexed_states {
    float indexed[2];
    float& speed() { return indexed[0]; }
    float& position() { return indexed[1]; }
};

コンパイラーはアクセサーのインライン化に問題がないため、読み取りまたは書き込みが可能でspeed()ありposition()、メンバー・データであるかのように高速になります。ただし、これらの厄介な括弧を作成する必要があります。

于 2012-08-14T17:26:36.387 に答える
2

ユニオンの最後に書かれたメンバーにのみアクセスすることは明確に定義されています。提示したコードは、標準のC(またはC ++)のみに関する限り、未定義の動作を使用します。これは機能する可能性がありますが、間違った方法です。構造体が配列の型と同じ型を使用することは実際には問題ではありません-パディングが含まれる可能性があり、コンパイラによって使用される他の目に見えないトリックも含まれる可能性があります。

GCCのような一部のコンパイラは、型のパンニングを実現するための許可された方法としてGCCを定義しています。ここで疑問が生じます-標準のC(またはC ++)、GNU、またはその他の拡張機能について話しているのでしょうか?

使用すべきものについては、適切な変換演算子やコンストラクター、あるいはその両方です。

于 2012-08-14T17:21:02.463 に答える
1

これは少し古風かもしれませんが、この状況で私がすることは次のとおりです。

列挙型{

F_POSITION、

F_SPEED、

F_COUNT};

フロート状態[F_COUNT];

次に、それらをstates[F_POSITION]およびstates[F_SPEED]として参照できます。

それは私がこれを書くかもしれない1つの方法です。他にもたくさんの可能性があると思います。

于 2012-08-14T17:29:11.393 に答える