2
union
{
    Uint32 Integer;
    Float32 Real;
} Field;    

IEEEのちょっとしたトリックにそのユニオンを使用する必要がありますが、それは厳密なエイリアシングを破りますか?GCCは警告をスローしていません(衒学的な厳密なエイリアシングでもGCC 4.5および4.6で試しましたが、私が知る限り、GCCは厳密なエイリアシングルールの違反(多くの誤検知/ネガティブ)をうまくキャッチできません。

Field A;
A.Integer = (Value1 & B) || Value2;
return A.Real;

これは私が現在使用しているスニペットであり、警告なしで正しく機能しているように見えますが、特定のコンパイラの最適化では、副作用や未定義の動作が発生する可能性があります。したがって、そのコードが特定の条件下で安全でない可能性がある場合は、それを削除するためにいくつかの努力をします。

また、このコードでは、データを標準レジスタから最新のCPUのフローティングポインティングレジスタに移動する必要があり(これについては興味があります)、古いCPUに比べて余分なサイクルが必要になると思います。

上記のコードは最適化を意図したものではないので、最適化を悪用することを誹謗中傷しないでください。上記のコードは、特定の結果を取得するための最も簡単な方法でした(幸い、最も簡単な方法は、私の場合!)、結果が安全でない場合は、より遅い方法を使用します。

前もって感謝します

4

2 に答える 2

1

共用体によるエイリアシングは C で定義されていますが、C++ では未定義の動作をします。未定義の動作は、初期化されていない変数 (左辺値から右辺値への変換) から読み取るときに発生する動作と同等です。

したがって、これが壊れる可能性が最も高いのは、定義された値がないため、ユニオンから読み取りを削除することをオプティマイザーが決定することです。ただし、ほとんどの C および C++ コンパイラは、とにかくそれをサポートする必要があるため、C の動作を提供する可能性があります。

値のエイリアスを作成する安全な方法は、バイト単位のコピー (例: std::memcpyor )std::copy(reinterpret_cast<char *>(...), ...)です。または、C と C++ の両方でプロジェクトをコンパイルできる場合は、ユニオン エイリアス コードを C ソース ファイルに移動し、そのコードだけを C としてコンパイルできます。

于 2012-09-25T17:35:17.703 に答える
0

UB です (厳密なエイリアシングは必要ありません)。また、uniond データは実装によって常にメモリに格納されますが、そうでない場合は、ソース データがどのレジスタから来たかを知る必要があります。つまり、ソース タイプを知る必要があります。

于 2012-09-25T17:04:20.257 に答える