为什么编译器不会生成警告?int test (unsigned int i = -1);

3

默认情况下,无符号整数不能为负。编译器会生成一个警告。 这很好。 但是,当我在一个带有负默认值的函数中做同样的事情时,它没有生成警告,这一点并不清楚。

unsigned int test(unsigned int i = -1) { return i;} // no warnings! Why?

int main()
{
   unsigned int i = -1;        // warning warning C4245 (ok!)
   unsigned int j = test();    // no warnings!  Why?     
}
2个回答

3

我认为你的编译器应该警告你默认参数是负数。但编译器并不完美。(标准允许将负整数值转换为无符号类型。)

至于在调用test()时发出的警告,可怜的编译器怎么知道test()将始终返回-1?函数的定义甚至可能位于不同的编译单元中!(尽管在你的情况下不是这样,但编译器在发出警告时不应该想到这一点。)

如果test带有constexpr限定符,则情况将有所不同,编译器应该能够发出警告。


1
我使用 G++ 5.1 进行了测试,constexpr 在这种情况下似乎不会生成任何警告。 - Frxstrem
嗯,我认为应该这样做。那么像-1.1这样的东西怎么办?它实际上是未定义行为。 - Bathsheba
@Bathsheba 你的意思是 unsigned int i = -1.1 是未定义行为吗? - Jonathan Mee
它肯定是用C语言编写的。这是今天关于此问题的一个问题:https://dev59.com/lVoV5IYBdhLWcg3wTdIb#48jnnYgBc1ULPQZFbDo7 - Bathsheba

2
这种转换是允许的,无需强制转换,但前提是你准备好承担后果:

无符号整型对象可以转换为对应的有符号类型。然而,如果无符号对象的值超出了有符号类型可表示的范围,这样的转换可能会导致数据被错误解释。

但是,当你进行从有符号类型到无符号类型的转换并再次转换回来时,数据将被保留

1
确实是允许的(有趣的是,-1.0也被允许,但比它更低的浮点值是未定义行为),但我对这个(好)问题的理解是为什么编译器没有警告你。 - Bathsheba
当 OP 将有符号的 -1 赋值给 i 时,编译器知道数据将超出 unsigned 可表示的范围,因此会发出警告。我唯一猜测 C++ 标准不要求在可能发生误解的情况下发出警告的原因是它保证了相同的位表示,并且无操作带来的潜在危害是有限的。 - Sergey Kalinichenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接