5

当我尝试使用启用了警告级别 /W4 的 Visual Studio 2010 C++ 编译器 (X86) 编译以下 C++ 程序时,我在标记的行处收到有符号/无符号不匹配警告。

#include <cstdio>
#include <cstdint>
#include <cstddef>

int main(int argc, char **argv)
{
    size_t idx = 42;
    uint8_t bytesCount = 20;

    // warning C4389: '==' : signed/unsigned mismatch
    if (bytesCount + 1 == idx)
    {
        printf("Hello World\n");
    }

    // no warning
    if (bytesCount == idx)
    {
        printf("Hello World\n");
    }
}

这让我很困惑,因为我只使用无符号类型。由于比较

bytesCount == idx

没有引起这样的警告,它可能与这里发生的一些奇怪的隐含对话有关。

因此:我收到此警告的原因是什么以及此对话发生的规则是什么(如果这是原因)?

4

4 回答 4

9

1 是有符号的文字。试试 bytesCount + 1U。

由于添加了有符号和无符号值( bytesCount + 1 ),编译器可能正在创建有符号类型的临时值

于 2011-12-19T19:08:58.063 回答
5

1是一个int。整数算术表达式的类型取决于所涉及的类型。在这种情况下,您有一个unsigned类型和一个signed类型unsigned小于该类型的signed类型。这属于表达式的 C++ 标准(第 5.10 节 [expr]):

否则,如果带符号整数类型的操作数的类型可以表示无符号整数类型的操作数类型的所有值,则将无符号整数类型的操作数转换为有符号整数类型的操作数的类型。

即,表达式的类型bytesCount + 1int默认签名的。

于 2011-12-19T19:19:25.097 回答
3

因为 1 是类型int,所以表达式bytesCount + 1int(有符号的)。

事实上,当在数学表达式中使用小于的类型时int,它会被提升为int,所以偶数+ bytesCountbytesCount + bytesCount被认为是int而不是uint8_t(whilebytesCount + 1U是一个,因为unsigned int大于int)。

以下程序输出true3 次。

#include <iostream>

int main() 
{
    unsigned short s = 1;
    std::cout << (&typeid( s + 1U ) == &typeid(1U)) << std::endl;
    std::cout << (&typeid( + s ) == &typeid(1)) << std::endl;
    std::cout << (&typeid( s + s ) == &typeid(1)) << std::endl;
}
于 2011-12-19T19:09:59.997 回答
1

The other answers already tell you that bytesCount + 1 is interpreted as signed int. However, I'd like to add that in bytesCount == idx, bytesCount is also interpreted as signed int. Conceptually, it is first converted to signed int, and it is only converted to unsigned int after that. Your compiler does not warn about this, because it has enough information to know that there is not really problem. The conversion to signed int cannot possibly make bytesCount negative. Comparing bytesCount + 1 is equally valid, equally safe, but just that slight bit more complex to make the compiler no longer recognise it as safe.

于 2011-12-19T19:23:32.677 回答