1. ホーム
  2. c++

[解決済み] トラップ表現

2023-03-21 05:58:52

質問

  1. C言語における"trap representation"とは何ですか(いくつかの例が役に立つかもしれません)?これは C++ に適用されるのでしょうか?

  2. このコードが与えられると...

    float f=3.5;
    int *pi = (int*)&f;
    
    

    ... と仮定すると sizeof(int) == sizeof(float) を行う。 f そして *pi は同じバイナリ表現/パターンを持つのでしょうか?

どのように解決するのですか?

  1. トラップ表現は、C99 で使用されるキャッチオールな用語で (IRC、C89 では使用されません)、型によって占有されるスペースに適合するが、その型の値として使用すると未定義の動作を引き起こすビットパターンを記述するために使用されます。 定義はセクション6.2.6.1p5(6.2.6全体に触手を伸ばしている)にあり、長くてわかりにくいのでここでは引用しない。 このようなビットパターンが存在する型は、トラップ表現を持つ("have")と言われています。 どの型もトラップ表現を持つ必要はありませんが、規格が保証している唯一の型は ではなく がトラップ表現を持つことを保証する唯一の型は unsigned char になります (6.2.6.1p5, 6.2.6.2p1).

    規格では、トラップ表現の 2 つの仮説的な例を挙げていますが、どちらも実際の CPU が長年行ってきたことに対応しないため、混乱させるつもりはありません。 A 良い トラップ表現の例 (これも だけ の例では、浮動小数点型の信号 NaN がトラップ表現 (遭遇する可能性のあるすべての CPU でハードウェアレベルのトラップ表現として適格なもの) となります。 C99 Annex F (セクション 2.1) は、IEC 60559 がその動作を詳細に指定しているにもかかわらず、シグナリング NaN の動作を明示的に未定義のままにしています。

    言及する価値があるのは、ポインタ型 はトラップ表現を持つことが許されていますが、ヌルポインタは ではなく トラップ表現ではありません。 Null ポインタは、デリファレンスまたはオフセットされた場合にのみ未定義の動作を引き起こし、それ以外の操作(最も重要な比較とコピー)は適切に定義されています。 トラップ表現では、単に 読む トラップ表現は、トラップ表現を持つ型を使用してそれらを読み取るだけで、未定義の動作を引き起こします。 (トラップ表現を持つ 無効 が NULL でないポインタがトラップ表現とみなされるか、またはみなされるべきかは、議論の余地があります。 CPU はそのように扱わないが、コンパイラーはそのように扱うかもしれない)。

  2. あなたが示したコードには未定義の動作がありますが、これはポインタエイリアスのルールのためであり、トラップ表現のためではありません。 これは floatint を同じ表現で表現する(と仮定すると、おっしゃるように sizeof(float) == sizeof(int) )

    int extract_int(float f)
    {
        union { int i; float f; } u;
        u.f = f;
        return u.i;
    }
    
    

    このコードには 不特定 (未定義ではない) 動作であり、基本的に標準では どのような整数値 が生成されるのですが、その際に いくつかの のような有効な整数値であれば、トラップ表現ではないので、コンパイラはこれをやっていないことを前提に最適化することは許されません。 (セクション 6.2.6.1, パラ7. 私の C99 のコピーには技術的な修正案が含まれているかもしれませんが、私の記憶では、この でした。 は元の出版物では未定義でしたが、TC で未定義に変更されたと記憶しています)。