当我尝试使用启用了警告级别/ 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
没有引起这样的警告,这可能与这里发生的一些奇怪的隐性对话有关。
因此:我得到这个警告的原因是什么,以及这种对话发生的规则(如果这是原因)?
答案 0 :(得分:9)
1是签名文字。尝试使用bytesCount + 1U。
由于添加了有符号和无符号值(bytesCount + 1),编译器可能正在创建签名类型的临时值
答案 1 :(得分:5)
1
是int
。整数算术表达式的类型取决于所涉及的类型。在这种情况下,您有unsigned
类型和signed
类型,其中unsigned
类型小于signed
类型。这属于表达式的C ++标准(第5.10节[expr]):
否则,如果带有符号整数类型的操作数的类型可以 表示带有unsigned的操作数类型的所有值 整数类型,带无符号整数类型的操作数应为 转换为带有符号整数类型的操作数类型。
即表达式bytesCount + 1
的类型是int
,默认情况下会签名。
答案 2 :(得分:3)
由于1属于int
类型,因此表达式bytesCount + 1
为int
(已签名)。
事实上,当在数学表达式中使用小于int
的类型时,它会被提升为int
,因此即使+ bytesCount
和bytesCount + bytesCount
也会被视为int
而不是uint8_t
(而bytesCount + 1U
是unsigned int
,因为大于而不是int
。)
following program输出true
三次。
#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;
}
答案 3 :(得分:1)
其他答案已告诉您bytesCount + 1
被解释为signed int
。不过,我想在bytesCount == idx
中添加bytesCount
,也解释为signed int
。从概念上讲,它首先转换为signed int
,然后仅转换为unsigned int
。您的编译器不会对此发出警告,因为它有足够的信息来确定没有真正的问题。转换为signed int
不可能使bytesCount
为负数。比较bytesCount + 1
同样有效,同样安全,但只是稍微复杂一点,使编译器不再认为它是安全的。