2016-06-23 12 views
6

以下のプログラムは厳密なエイリアシング規則に違反していますか?厳密なエイリアス違反

#include <cstdint> 

int main() 
{ 
    double d = 0.1; 

    //std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation 

    //auto n{*reinterpret_cast<std::int64_t*>(&d)}; // aliasing violation 

    auto nptr{reinterpret_cast<std::int64_t*>(&d)}; 
    auto& n{*nptr}; 

    ++n; 
} 

VS2015、clang又はgccによって放出された無警戒。

答えて

5

次のプログラムは厳密なエイリアシング規則に違反していますか?

はい、あります。 std::int64_t*を使用してdouble*&d)を参照解除しています。

厳格なエイリアシング規則に違反する行は次のようになります。

auto& n{*nptr}; 

ラインの処理中に、コンパイラは、必ずしもあなたがnptrの値を設定する方法がわかりません。 double*へのエイリアスであるという事実は、その行を処理している間は明らかではありません。

5

はい、厳密なエイリアシングに違反します。 doubleのオブジェクトdにアクセスしていますが、ポインタnptrdoubleへのポインタではありません。

コンパイラが警告を発していないということは違反ではないということではありません。厳密に発生する違反はUBです(実行時の動作の問題であるため)、したがって診断は必要ありません。

+0

Re "厳密な[エイリアシング]の違反はUBです"、まったくありません。厳密なエイリアシングは、その最適化に関連するgccの概念です。代わりに、C++標準では、再解釈の結果を移植可能な方法でどのように使用できるかどうかについてのルールがあります。この例では、正式なUBを引き起こします。しかし、この例は、特定のプラットフォームでうまくいく可能性があります。 –

+0

@ Cheersandhth.-Alf: "* C++標準には、再解釈の結果をポータブルな方法でどのように使用できるかについてのルールがあります。この用語はGCCオプションから来るかもしれませんが、ルール自体はありません。だから私はあなたのポイントが何かを見ていない。いいえ、この例では、どのプラットフォームでも明確に定義された動作が許可されていません。 3.10/10では、 'int64_1'へのポインタを通して' double'の値に*常に*アクセスすることはできません。 –

+0

CおよびC++ *が特定のプラットフォームでの型打ちを行うことができないという見解は、現実に反しています。その応答は、私が指摘しようとしてきたことの非常に良い例です。残念なことに、この見解は、g ++(そしてプラグインの置き換えとしてのclang)をそれほど実用的でないものにしています。 –