3

私のプログラムでは、何か特別なことを示すために、符号なし変数の値として -1 (別名 UINT_MAX) をよく使用します。また、この値と比較します。より高いレベルの警告メッセージをオンにすると、コンパイラ (VS と GCC の両方) がこの構文を好まないことが明らかになります。

// warning C4245: 'initializing' : conversion from 'int' to 'unsigned int', signed/unsigned mismatch
unsigned a = -1;

// warning C4146: unary minus operator applied to unsigned type, result still unsigned
unsigned b = -1U;

// fine but messy
unsigned c = unsigned(-1);

// no warning on VS, signed/unsigned comparison warning with GCC
if (a == -1)
{
  std::cout << "check\n";
}

質問 1: 上記の構文 (それぞれの場合) は正当な C++ コードですか?

質問 2: unsigned(-1) を使用して unsigned int に代入/比較するすべての場所で、本当に unsigned(-1) を記述する必要がありますか? または、コンパイラの警告をトリガーしないよりクリーンな方法はありますか?

4

6 に答える 6

6

その性質上、負の値を C++ やその他の言語で符号なしリテラルとして記述することはできません。

-1というわけではありませんstd::numeric_limits<unsigned int>::max()

#include <iostream>
#include <limits>

int main()
{
    unsigned a = std::numeric_limits<unsigned int>::max();

    if (a == std::numeric_limits<unsigned int>::max())
    {
        std::cout << "check " << a << "\n";
    }
}

C++11 標準により、この関数が作成されましconstexprた。これにより、関数がコンパイル時の定数であることが保証されます。(さらに読む)。

古いコンパイラを使用してループの反復ごとにこれを計算することを避けたい場合は、ループのconst外側に を作成し、これを比較します。

const unsigned int magic_number = std::numeric_limits<unsigned int>::max();

    // [...]
    if (a == magic_number)
于 2012-04-18T19:48:46.727 に答える
4

答え 1:

はい、間違いなく不快ではありますが、どちらも適切な C++ 構造です。

  • -1int リテラルとして解釈されます。標準では暗黙的な int から unsigned int への変換が許可されているため、これは適切な C++ 構文ですが、この暗黙的な変換がより高い警告レベルで使用されると、コンパイラは警告します。
  • -1Uと解釈され-(1U)ます。unsigned int の負の値を取るのは適切な C++ 構文です。コンパイラはこの演算 modulo を実行しますが(UINT_MAX + 1)、コンパイラは警告を発行して知らせます。
  • (unsigned(-1) == -1)も適切な構文です。これは、コンパイラが比較のために暗黙的に に変換-1するためです。unsigned(-1)より高い警告レベルで暗黙的な変換について警告し、変換したことを知らせます。

答え 2:

unsigned(-1)リテラルとして記述または実行するためのオプションがいくつかあります。

  • 書いてくださいunsigned(-1)
  • Write~0Uは、2 の補数マシンで、0各ビットを取り、それを否定します。これにより、表現可能な最大の符号なし数値が得られます。
  • UINT_MAX実質的に#defined となるものを と書きunsigned(-1)ます。
  • 符号なしの値が割り当てられているか、それと比較されている場合は、書き込み-1、コンパイラに暗黙的な変換を行わせ、警告メッセージに対処します。ただし、-1 は int リテラルであり、コード内の関数に基づいて unsigned にのみ変換されることに注意してください。
  • std::numeric_limits<unsigned>::max()を返す関数を書きますunsigned(-1)。C++11 では、この関数は constexpr になり、優れたコンパイラは常にリテラルに単純化する必要があることに注意してください。unsigned(-1)VC++ は現在、これを非デバッグ ビルド用に簡略化しています。ただし、これは関数呼び出しから返される値であり、リテラルではありません。
于 2012-04-20T02:53:45.643 に答える
1

この記事の最後にあるディスカッション スレッドを確認してください。

http://embeddedgurus.com/barr-code/2011/06/is-uint16_t-1-portable-c-code/

つまり、(unsigned)(-1) は完全に合法であり、実際の幅や内部表現に関係なく、その型の最大値を持つことが保証されています。

それが良いアイデアかどうかは別の問題です。個人的には、Johnsyweb が提供するソリューションを好みます。

常にキャストが必要かどうかについては、コンパイラに依存します。VS と GCC を試したので、そのようです。

于 2012-04-20T03:31:42.563 に答える
1

int の長さを処理する必要がないようにするには、次を使用できます。

~0

これにより、すべて 1 が得られます。これは、2 の補数のマシン (最近はまだ他にありませんか?) では -1 と同じです。しかし、それは正当な署名のない長いです。

于 2012-04-18T19:38:05.443 に答える
0

ULONG_MAX だけを使用するのはどうですか? limits.h を含める必要があります。

あるいは、マクロまたは静的定数で適切に定義された 0xFFFFFFFF を使用することもできます。

于 2012-04-18T19:32:03.193 に答える
0

無署名と署名を混同すべきではないと思います。-1 は Signed であり、そのままにしておく必要があります。設計上の問題で、頻繁に -1 を使用したい場合があります。boost::optional のようなソリューションがあります。

http://www.boost.org/doc/libs/1_49_0/libs/optional/doc/html/index.html

例:

#include <boost/optional.hpp>
#include <iostream>

boost::optional<int> find (const std::string& s, char t)
{
   for (int i = 0 ; i < s.length () ; ++ i)
   if (s [i] == t)
   return i ;
   return boost::optional<int>() ;
}

int main (int argc, char* argv[]) 
{
    std::string s = argv[1] ;
    char t = *argv[2] ;
    boost::optional<int> idx = find (s, t) ;
    if (idx)
        std::cout << "found at " << *idx << std::endl ;
    else
        std::cout << "not found" << std::endl ;

   return 0 ;
}
于 2012-04-18T19:32:54.880 に答える