2017-11-14 12 views
4

標準ライブラリvector::size()は、size_t(符号なしの数値)を返します。 CppConの講演の中で私は誰か(Chandler Carruthだったのですか?)は聞いたことがありますが、これは残念であり、符号付き整数を使うべきだと言います。サイズに符号付き整数または符号なし整数を使用する必要がありますか?

符号付き整数に対してオーバーフローが定義されていないという背景があるため、コンパイラの方がはるかに余裕があります。 Carruth氏は、bzip2のforループインデックスとしてuint8_tがどのようにしてint8_tよりも多くのマシン命令を作成することを示しました。マスクとシフトでオーバーフローを明示的にシミュレートする必要があるからです。

私が今作業しているコードでは、厳密にポジティブな特定のサイズがあります。これらはsize_tと表されます。これは、彼らが否定的ではないことを示しているので、まともではないようです。一方、定義されたモジュラ算術は必要ありません。したがって、符号付き整数が十分に大きい(200になる)限り、符号なし整数は、必要とする算術演算に対して間違ったインタフェースを持ちます。

コードのある時点では、このサイズから0までのループがあります。そして、ループインデックスが減算され、絶対値が取られます。

最近のGCC 7でコンパイルしたとき、size_t - size_tが明らかに曖昧な値を与えるので、std::absの適切なオーバーロードを解決できませんでした。私は、ループインデックスにintを使用するコードを変更しました:

for (int t1 = 0; t1 < Lt; t1++) { 
    for (int t2 = 0; t2 < Lt; t2++) { 

abs(t1 - t2)だけで正常に動作します。しかし、比較t1 < Ltは、符号付きと符号なしの数値の比較であるため、警告を出します。

正しいアプローチは何ですか?

  1. 符号なし整数を使用して、負でないものを使用してから、引き算を行う必要があるときはいつでもstatic_cast<int>()を使用します。
  2. ループインデックスには符号付き整数を使用しますが、コンテナのサイズには符号なし整数を使用します。次に、比較にstatic_cast<int>を使用します。
  3. どこでも符号付き整数を使用してください。他のライブラリが符号なし整数を返すときは、警告を満たすためにそこにstatic_cast<int>を使用してください。
+0

"これは負の値ではないことを示しているので、まともではないようです*"しかし、モジュラ算術に従うことになっていますか? – juanchopanza

+3

符号付きの値が必要な場合は、 'int'ではなく' ssize_t'(余分な 's')に注意してください。 –

+1

[This](https://stackoverflow.com/questions/10040884/signed-vs-unsigned-integers-for-lengths-counts)は面白いかもしれません。 –

答えて

1

「の話では、Carruthは、それが明示的にマスクやシフトでオーバーフローをシミュレートすることがあるため、bzip2でのループのための指標としてuint8_tがint8_tよりもx86の上より多くのマシン命令を作成する方法を紹介しました。」

どちらのタイプも使用できる場合、範囲は[0, 127]に制限する必要があります。インデックスタイプとしてintを使用してください。基本的な算術演算のための自然な型の定義であるは、であり、通常はCPUレジスタによくマッピングされます。

最小限のストレージに最適化されたタイプを使用しても、最速の計算は生成されません。それは驚きではありません。このような欠陥のある設定に基づいて、署名されたものと署名されていないものとの結論を引き出すことはできません。

-

"をsize_tsize_tはあいまいな値を示し、" まあ、それはしていませんが、それは剰余演算を使用して行います。 size_t(1)-size_t(2)==size_t(-1)ですが、size_t(-1)が可能な限り大きな値です。これは、モジュラ演算の定義から直接得られます。(x-1がラップアラウンドする場合を除き、x==0)。 (又は同等x+1>xx+1==0場合を除く)すべてのsize_t値が正であるので、abs(size_t(x))を呼び出す

も従って無意味です。また、符号付き整数をsize_tと比較すると、意図しない結果が同様に発生します。彼らが結果を明確にするので、明示的なキャストは良いです。

しかし、適用するキャストを自動的に特定する汎用的な解決法はありません。機械的なルールを発明できれば、そのルールをコンパイラに任せることができました。私達はできないので、私たちは持っていません。あなたはプログラマとして、各ケースを数値的に考慮する必要があります。

関連する問題