9

カウント クラス メンバーに符号なし整数を使用する必要がありますか?

答え

たとえば、クラスを想定します

TList <T> = class
private
  FCount : Cardinal;
public
  property Count : Cardinal read FCount;
end;

それは理にかなっていますね。リストに格納されるアイテムの数を負にすることはできないので、符号なし整数型を使用しないのはなぜですか? 一般的には、可能な限り一般的でない (つまり、最も特殊な) 型を常に使用するのが良い原則だと思います。

リストを反復処理すると、次のようになります。

for I := 0 to List.Count - 1 do
  Writeln (List [I]);

リストに格納されているアイテムの数が 0 の場合、コンパイラは次の評価を試みます。

List.Count - 1

これにより、適切な整数オーバーフロー (正確にはアンダーフロー) が発生します。デバッガーが例外が発生した適切な場所を表示しないという事実と相まって、これを見つけるのは非常に困難でした。

オーバーフロー チェックをオフにすると、結果として生じるエラーを追跡するのがさらに難しくなります。これは、自分のものではないメモリにアクセスすることが多くなり、未定義の動作が発生するためです。

このような状況を避けるために、今後はすべてのカウント メンバーにプレーンな整数を使用します。

それが完全にナンセンスである場合は、私に指摘してください:)

(コード内の整数オーバーフローを追跡するのに 1 時間費やしたので、それを共有することにしました。もちろん、ここにいるほとんどの人はそれを知っているでしょうが、おそらく誰かの時間を節約できるでしょう。)

4

6 に答える 6

15

いいえ、絶対に違います。Delphi のイディオムは、ここで整数を使用することです。言語と戦わないでください。32 ビット環境では、ビットマップを構築しようとする場合を除いて、リストにそれ以上の要素はありません。

はっきりさせておきます。あなたのコードを使わなければならないすべてのプログラマーは、整数の代わりにカーディナルを使うあなたを嫌うでしょう。

于 2009-04-28T12:03:19.853 に答える
10

通常、ある時点で式の中で符号付き整数と符号なし整数を混在させることになるため、符号なし整数は、ほとんどの場合、価値があるよりも問題が多くなります。つまり、正しいセマンティクスを取得するには、型を拡張する必要があり (そしておそらくパフォーマンス ヒットが発生する) (理想的には、コンパイラは言語定義に従ってこれを行います)、そうでない場合は、範囲チェックに非常に注意する必要があります。

C/C++ を例にとるsize_tと、 はメモリ サイズと割り当ての整数の型であり、符号なしですがptrdiff_t、あるポインタから別のポインタを減算するときに取得するオフセットの型であり、必ず符号付きです。配列に割り当てた要素の数を知りたいですか? おそらく、first要素アドレスから要素アドレスを引き、last+1で割りsizeof(element-type)ますか? これで、符号付き整数と符号なし整数を混在させることができました。

于 2009-04-28T14:09:52.700 に答える
9

「可能な限り一般的でない(最も特別な)タイプを常に使用することは、一般的には良い原則だと思います」というあなたの声明について。-実際には、不安やトラブルが最も少ないデータ型を使用するのが良い原則だと思います。

一般的に私にとっては、それはsigned intです:

  1. 通常、2 31個以上の要素を含むリストはありません。
  2. それほど大きなリストを持つべきではありません:-)
  3. コードに特殊なエッジ ケースを含める手間が嫌いです。

しかし、それは実際にはスタイルの問題です。コードの「純粋さ」がコードの簡潔さよりも重要である場合は、その方法が最適です (エッジ ケースをキャッチするための変更を加えたもの)。私自身、エッジケースはコードを混乱させ、理解を減らす傾向があるため、簡潔にすることを好みます。

于 2009-04-28T12:01:35.503 に答える
8

しないでください。

これはプログラミングのイディオムに反するだけではなく、符号なし算術演算を使用するようにコンパイラに明示的に要求するものであり、異常な動作 (オーバーフローを防止しない場合) または無関係な実行時例外 (オーバーフローを防止する場合) が発生する可能性があります。一時的なオーバーフローは致命的です。最終結果が正であっても、追加する前に減算すると、私は CPU オペコード レベルの操作の順序を参照しています。コード)。

「符号なし」は「正」に変換され、「符号がない」に変換されることに注意してください。これは異なります。「署名なし」という用語が選ばれたのには正当な理由があります (そして、Delphi で「枢機卿」と名付けることは、IMO の不適切な選択でした)。

符号なし型は、未加工のストレージ仕様、ビットごとの操作、ASM コード、組み込みコントローラー、およびその他の特殊な用途に使用されます。高水準のプログラミングを行っているときは、unsigned 型について聞いたことがあることを忘れてはなりません。

于 2009-04-28T21:02:54.237 に答える
3

道徳:foreachこの質問を完全に回避するため、可能な場合はイテレータを使用してください。

于 2009-04-28T11:57:18.760 に答える
3

境界条件はしばしば問題を引き起こします。負になる可能性のある型を許可すると、問題がシフトする可能性があります。おそらく、デバッグしやすいようにシフトするかもしれませんが、そうではないかもしれません。このようなループをカウントするために整数を使用することから始めましたが、後でエラーを検出するために基数に切り替えました。

于 2009-04-28T11:58:42.953 に答える