如何在C ++中将否定的一个写为无符号文字

时间:2012-04-18 19:27:45

标签: c++ literals unsigned

在我的程序中,我经常使用-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 int时,我是否真的必须写无符号(-1)或者是否有更简洁的方法不会触发编译器警告?

6 个答案:

答案 0 :(得分:5)

就其本质而言,你不能用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保证函数是编译时常量。 (Further reading)。

如果您想避免使用较旧的编译器为循环的每次迭代计算此值,请在循环外创建const并比较它:

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

    // [...]
    if (a == magic_number)

答案 1 :(得分:4)

答案1:

是的,它们都是正确的,尽管可以说是令人不愉快的C ++结构。

  • -1被解释为int文字。这是正确的C ++语法,因为标准允许对无符号的int转换进行隐式int,但编译器会在更高的警告级别使用此隐式转换时发出警告。
  • -1U被解释为-(1U)。使用unsigned int的否定是正确的C ++语法,因为编译器以(UINT_MAX + 1)模式执行此操作,但编译器会发出警告让您知道。
  • (unsigned(-1) == -1)也是正确的语法,因为编译器会隐式地将-1转换为unsigned(-1)以进行比较。它会警告你在更高警告级别的隐式转换,让你知道它已经这样做了。

答案2:

有几种选项可以将unsigned(-1)写成或影响为文字:

  • 撰写unsigned(-1)
  • ~0U,在两个竞争机器上,取0然后否定每个位,这给出了最大的可表示无符号数。
  • 将有效UINT_MAX d #define写为unsigned(-1)
  • 如果已分配或比较无符号值,请编写-1并让编译器执行隐式转换并处理警告消息。但是,应该注意-1是一个int文字,只能根据代码中的函数转换为unsigned。
  • std::numeric_limits<unsigned>::max()这是一个返回unsigned(-1)的函数。请注意,在In C ++ 11中,这个函数将是一个constexpr,一个好的编译器应该总是简化为一个文字。对于非调试版本,VC ++目前将其简化为unsigned(-1)。但是,它是从函数调用返回的值,而不是文字。

答案 2 :(得分:1)

为了避免必须处理int的长度,你可以使用

~0

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

答案 3 :(得分:1)

查看本文末尾的讨论主题。

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

结果是(无符号)( - 1)是完全合法的,并保证具有该类型的最大值,无论实际宽度或内部表示如何。

这是否是一个好主意是另一个问题。就个人而言,我更喜欢Johnsyweb提供的解决方案。

至于你是否总是需要演员表,这将取决于编译器。既然你已经尝试过VS和GCC,那就好了。

答案 4 :(得分:0)

如何使用ULONG_MAX? 您需要包含limits.h。

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

答案 5 :(得分: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 ;
}