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:我真的必须在使用此值分配/比较无符号 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++ 结构。

  • -1被解释为 int 字面量。这是正确的 C++ 语法,因为该标准允许将隐式 int 转换为 unsigned int,但是当在更高的警告级别使用此隐式转换时,编译器会发出警告。
  • -1U被解释为-(1U)。取 unsigned int 的负数是正确的 C++ 语法,因为编译器执行此操作 modulo (UINT_MAX + 1),但是编译器会发出警告让您知道。
  • (unsigned(-1) == -1)也是正确的语法,因为编译器隐式转换-1unsigned(-1)进行比较。它确实会警告您有关更高警告级别的隐式转换,以让您知道它已经这样做了。

答案 2:

有几个选项可以写成unsigned(-1)文字或效果:

  • unsigned(-1)
  • Write ~0U,在二进制补码机器上,取0然后否定每个位,这给出了最大的可表示无符号数。
  • 写出UINT_MAX有效的#defined 为unsigned(-1)
  • 如果分配或与无符号值进行比较,请编写-1并让编译器进行隐式转换并处理警告消息。但是,应该注意的是,-1 是一个 int 字面量,只能根据其在代码中的功能转换为无符号数。
  • std::numeric_limits<unsigned>::max()which 是一个返回的函数unsigned(-1)。请注意,在 C++11 中,此函数将是一个 constexpr,一个好的编译器应始终将其简化为文字。VC++ 目前将其简化unsigned(-1)为非调试版本。但是,它是从函数调用返回的值,而不是文字。
于 2012-04-20T02:53:45.643 回答
1

为避免不得不处理 int 的长度,您可以使用

~0

这给了你所有的,在二进制补码机器上(现在还有其他机器吗?)与 -1 相同。但这是一个合法的无符号长。

于 2012-04-18T19:38:05.443 回答
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 回答
0

只使用 ULONG_MAX 怎么样?您需要包含limits.h。

或者,您也可以使用 0xFFFFFFFF - 当然,在宏或静态常量中正确定义。

于 2012-04-18T19:32:03.193 回答
0

我认为您不应该将未签名和已签名的东西弄乱。-1 已签名并且应该保持这种方式,也许这是您希望经常使用 -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 回答