8

Dの整数オーバーフローを検出する方法は?(キャリーフラグをチェックしますか?)

元の例:

ubyte a = 100;
ubyte b = 200;
ubyte c = a + b;
// c can't represent 300; how to detect the overflow now?

改訂例:

uint a = 2_000_000_000;
uint b = 3_000_000_000;
uint c = a + b;
// c can't represent 5_000_000_000; how to detect the overflow now?

また、乗算とプリ/ポストインクリメントを使用します。

4

2 に答える 2

9

手始めに、あなたが与えたコードはコンパイルすらしません。なぜなら、サイズが。intで行われるよりも小さいすべての整数演算だからintです。したがって、の結果はでa + bありintint暗黙的にに変換されません。これはubyte、変換が狭くなるためです。に割り当てたい場合cは、キャストする必要があります。

ubyte c = cast(ubyte)(a + b);

さて、これは明らかにチェックされていない変換であり、喜んで詰め込ま44れます(これは、とcの値が与えられたキャストの結果であるため)。チェックされた変換が必要な場合は、次を使用します。100200std.conv.to

ubyte c = to!ubyte(a + b);

結果が要求された型に適合しないため、ConvOverflowException(のサブクラスである)がスローされます。ConvException

自分でキャストを行い、オーバーフローが発生したかどうかを確認したい場合は、基本的にC / C ++と同じボートに乗っており、キャリーフラグなどはありません。アセンブリコードで確認すると、そういうことがあるのか​​もしれません。知らない。しかし、言語は確かにそのようなものを提供していません。std.conv.to結果をチェックし、結果が大きすぎるか小さすぎるかを確認することで、それを把握します(引数の符号とタイプによって異なります)。

于 2012-11-25T04:13:30.110 に答える
7

2021年の更新:この手法は、最適化なしでdmdを使用する場合にのみ機能します(さらに、他のアプローチを実行する方がおそらく良いでしょう)。より多くの場合に機能するには、インラインアセンブリですべての操作を実行するか(オプティマイザーを壊す可能性があります)、操作の最後に確認できる引数core.checkedintを持つ操作を使用ref bool overflowedできます(これもインラインフレンドリーです)オプティマイザ用)。

元の投稿は次のとおりです。

インラインアセンブリを使用すると、非常に簡単に確認できます。

asm { jo overflowed; } // for checking signed types
// or
asm { jc overflowed; } // use this for checking unsigned types

/* continue going */

return;

overflowed:

/* do whatever to handle it */

注:関数を呼び出すとフラグがリセットされる可能性があるため、これを関数に入れることはおそらくできません。興味のある操作の直後にインラインに配置することをお勧めします。

演算子のオーバーロードを使用してオーバーフローをスローする型を作成することができます。http: //arsdnet.net/dcode/ranged.dはその一例です。または、モジュールは標準ライブラリのstd.bigintであり、任意の大きさの整数型を提供することでオーバーフローを回避していると思います。

于 2012-11-26T01:09:37.633 に答える