7

オーバーフロー フラグの場合、このフラグへのアクセスは、クロスアーキテクチャ プログラミングに大きな恩恵をもたらすように思われます。次のような符号付き整数のオーバーフローをチェックするために、未定義の動作に依存する安全な代替手段を提供します。

if(a < a + 100) //detect overflow

次のような安全な代替手段があることは理解しています。

if(a > (INT_MAX - 100)) //detected overflow

ただし、ステータス レジスタまたはその中の個々のフラグへのアクセスは、C 言語と C++ 言語の両方から欠落しているようです。この機能が含まれていない理由、またはこの機能が含まれないようにするために行われた言語設計の決定は?

4

3 に答える 3

8

C と C++ はプラットフォームに依存しないように設計されているためです。ステータス レジスタはありません。

最近では、符号付き整数演算を実装するために 2 の補数が広く使用されていますが、常にそうとは限りませんでした。1 の補数または符号と絶対値は、以前は非常に一般的でした。そして、C が最初に設計されたとき、そのような CPU はまだ一般的に使用されていました。たとえば、COBOL は、これらのアーキテクチャに存在する負の 0 と正の 0 を区別します。明らかに、これらのアーキテクチャでのオーバーフロー動作は完全に異なります!

ところで、オーバーフローを検出するために未定義の動作に頼ることはできません。

if(a < a + 100)

警告を書いてコンパイルします

if(true)

... (最適化がオンになっていて、特定の最適化がオフになっていない場合)。

また、警告に頼ることはできないことに注意してください。trueコンパイラは、条件が終了したとき、または同等の変換の後にのみ警告を発しますが、オーバーフローの存在下で条件がプレーンな/falseとして終了せずに変更される場合が多くあります。truefalse

于 2012-10-01T14:26:11.633 に答える
6
  • C++ は移植可能な言語として設計されているためです。つまり、多くの CPU (x86、ARM、LSI-11/2、ゲームボーイ、携帯電話、フリーザー、飛行機、人間操作チップ、レーザー剣などのデバイス) でコンパイルできる言語です。
    • CPU 間で使用可能なフラグは大きく異なる場合があります
    • 同じ CPU 内であっても、フラグが異なる場合があります (x86 スカラー命令とベクトル命令を使用)
    • 一部の CPU には、必要なフラグがまったくない場合があります
  • 質問に答える必要があります:コンパイラは、フラグが使用されているかどうかを判断できない場合、常にそのフラグを配信/有効にする必要がありますか? 、これは、C と C++ の両方の書かれていないが神聖な法則を使用するものだけに支払いを適合させるものではありません
  • コンパイラは、これらのフラグを有効に保つためにコードを最適化したり、並べ替えたりすることを禁止する必要があるためです。

後者の例:

int x = 7;
x += z;
int y = 2;
y += z;

オプティマイザは、これを疑似アセンブリ コードに変換する場合があります。

alloc_stack_frame 2*sizeof(int)
load_int 7, $0
load_int 2, $1
add z, $0
add z, $1

これは、より似ています

int x = 7;
int y = 2;
x += z;
y += z; 

間にレジスタをクエリすると

int x = 7;
x += z;
if (check_overflow($0)) {...}
int y = 2;
y += z;

次に、最適化と逆アセンブルの後、これで終了する可能性があります。

int x = 7;
int y = 2;
x += z;
y += z;
if (check_overflow($0)) {...}

これは正しくありません。

constant-folding-compile-time-overflow で何が起こるかなど、より多くの例を構築できます。


補足: 現在の CPU レジスタを読み取るための小さな API を持つ古い Borland C++ コンパイラを覚えています。ただし、最適化に関する上記の議論は依然として適用されます。

別の補足事項: オーバーフローを確認するには:

// desired expression: int z = x + y
would_overflow = x > MAX-y;

より具体的に

auto would_overflow = x > std::numeric_limits<int>::max()-y;

またはより良い、具体的ではない:

auto would_overflow = x > std::numeric_limits<decltype(x+y)>::max()-y;
于 2012-10-01T14:32:20.767 に答える
4

以下の理由が考えられます。

  1. register-flags へのアクセスを許可することにより、プラットフォーム間での言語の移植性が大幅に制限されます。

  2. オプティマイザーは式を大幅に変更し、フラグを役に立たなくする可能性があります。

  3. それは言語をより複雑にするでしょう

  4. ほとんどのコンパイラには、組み込み関数の大きなセットがあり、フラグを使用せずに最も一般的な操作 (キャリーによる加算など) を実行できます。

  5. ほとんどの式は、オーバーフローを回避する安全な方法で書き直すことができます。

  6. 非常に具体的なニーズがある場合は、いつでもインライン アセンブリにフォールバックできます

ステータス レジスタへのアクセスは、標準化の取り組みを行うには十分ではないようです。

于 2012-10-01T14:26:13.637 に答える