表达式 'i < 0' 始终为假
Expression 'i < 0' is always false
对于以下片段:
size_t i = 0;
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
PVS-Studio 分析记录第一个条件 i < 0
的警告,正如预期的那样:
V547 Expression 'i < 0' is always false. Unsigned type value is never < 0. test_cpp_vs2017.cpp 19
例如,为什么 PVS 不针对第二个也是可疑的情况发出任何警告 i != -1
报告它始终为真?
因为那将是一个无用的、无效的警告。 size_t
是无符号类型,由于整数转换的工作方式(参见 [conv.integral]/2),-1
转换(此处隐式)为 size_t
等于SIZE_MAX
.
考虑一下,这是 libstdc++ 中 std::string::npos
的实际定义:
static const size_type npos = static_cast<size_type>(-1);
如果 PVS-Studio 警告 i != -1
,是否还需要警告 i != std::string::npos
?
另一方面,无符号值永远不会小于 0,因为它是无符号的,所以 i < 0
可能不是程序员想要的,因此警告是有道理的。
这是由于两种情况下的隐式整数转换。 size_t
必须 是至少 16 位的无符号类型,并且在您的情况下它的大小足够 cf。 int
如果一个参数是 size_t
而另一个是 int
,那么 int
参数将转换为 size_t
。
计算 i < 0
时,0
被转换为 size_t
类型。两个操作数都是 size_t
所以表达式总是 false
.
计算i != -1
时,-1
也被转换为size_t
。该值将为 std::numeric_limits<size_t>::max()
.
参考:http://en.cppreference.com/w/cpp/language/implicit_conversion
当一个值被转换为无符号时,如果该值不能用无符号类型表示,那么该值将被转换为一个值(或者更确切地说, 值) 是 可表示的,并且与原始值模可表示值的数量一致(这是最大可表示值 + 1 == 2n其中 n 是位数)。
因此没有什么可警告的,因为有些值的条件可能为假(只要我们仅单独分析该表达式。i
始终为 0,因此条件为总是正确的,但为了能够证明这一点,我们必须考虑到程序的整个执行过程。
-1 与 m - 1 模 m 全等,因此 -1 始终转换为最大可表示值。
有正确的重要答案,但我想做一些澄清。不幸的是,测试示例的格式不正确。我们可以这样写:
void F1()
{
size_t i = 0;
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}
在这种情况下,分析器将发出两个 V547 警告:
- V547 表达式 'i < 0' 始终为假。无符号类型值从不
< 0。consoleapplication1.cpp 15
- V547 表达式 'i != - 1' 总是
真的。 consoleapplication1.cpp16
(V519也会发生,但与问题无关。)
因此,第一个 V547 警告被打印出来,因为无符号变量不能小于零。变量的值是多少也无关紧要。
发出第二个警告是因为分析器的反应是将 0 分配给变量 i,并且该变量在任何地方都没有改变。
现在让我们再写一个测试例子,让分析器对变量的值一无所知i
:
void F2(size_t i)
{
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}
现在只有一个V547警告:
- V547 表达式 'i < 0' 始终为假。无符号类型值永远不会 < 0。consoleapplication1.cpp 22
分析器无法说明 (i != -1)
条件。这是完全正常的,例如,它可以是与 npos
的比较,正如已经注意到的那样。
我写这篇文章是为了防止有人决定使用 PVS-Studio 测试源代码示例,将其排除在外。当他看到两个警告时,这个人会感到惊讶,尽管讨论的是只有一个。
对于以下片段:
size_t i = 0;
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
PVS-Studio 分析记录第一个条件 i < 0
的警告,正如预期的那样:
V547 Expression 'i < 0' is always false. Unsigned type value is never < 0. test_cpp_vs2017.cpp 19
例如,为什么 PVS 不针对第二个也是可疑的情况发出任何警告 i != -1
报告它始终为真?
因为那将是一个无用的、无效的警告。 size_t
是无符号类型,由于整数转换的工作方式(参见 [conv.integral]/2),-1
转换(此处隐式)为 size_t
等于SIZE_MAX
.
考虑一下,这是 libstdc++ 中 std::string::npos
的实际定义:
static const size_type npos = static_cast<size_type>(-1);
如果 PVS-Studio 警告 i != -1
,是否还需要警告 i != std::string::npos
?
另一方面,无符号值永远不会小于 0,因为它是无符号的,所以 i < 0
可能不是程序员想要的,因此警告是有道理的。
这是由于两种情况下的隐式整数转换。 size_t
必须 是至少 16 位的无符号类型,并且在您的情况下它的大小足够 cf。 int
如果一个参数是 size_t
而另一个是 int
,那么 int
参数将转换为 size_t
。
计算 i < 0
时,0
被转换为 size_t
类型。两个操作数都是 size_t
所以表达式总是 false
.
计算i != -1
时,-1
也被转换为size_t
。该值将为 std::numeric_limits<size_t>::max()
.
参考:http://en.cppreference.com/w/cpp/language/implicit_conversion
当一个值被转换为无符号时,如果该值不能用无符号类型表示,那么该值将被转换为一个值(或者更确切地说, 值) 是 可表示的,并且与原始值模可表示值的数量一致(这是最大可表示值 + 1 == 2n其中 n 是位数)。
因此没有什么可警告的,因为有些值的条件可能为假(只要我们仅单独分析该表达式。i
始终为 0,因此条件为总是正确的,但为了能够证明这一点,我们必须考虑到程序的整个执行过程。
-1 与 m - 1 模 m 全等,因此 -1 始终转换为最大可表示值。
有正确的重要答案,但我想做一些澄清。不幸的是,测试示例的格式不正确。我们可以这样写:
void F1()
{
size_t i = 0;
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}
在这种情况下,分析器将发出两个 V547 警告:
- V547 表达式 'i < 0' 始终为假。无符号类型值从不 < 0。consoleapplication1.cpp 15
- V547 表达式 'i != - 1' 总是 真的。 consoleapplication1.cpp16
(V519也会发生,但与问题无关。)
因此,第一个 V547 警告被打印出来,因为无符号变量不能小于零。变量的值是多少也无关紧要。 发出第二个警告是因为分析器的反应是将 0 分配给变量 i,并且该变量在任何地方都没有改变。
现在让我们再写一个测试例子,让分析器对变量的值一无所知i
:
void F2(size_t i)
{
std::wstring s;
s = (i < 0) ? L"ABC" : L"DEF";
s = (i != -1) ? L"ABC" : L"DEF";
}
现在只有一个V547警告:
- V547 表达式 'i < 0' 始终为假。无符号类型值永远不会 < 0。consoleapplication1.cpp 22
分析器无法说明 (i != -1)
条件。这是完全正常的,例如,它可以是与 npos
的比较,正如已经注意到的那样。
我写这篇文章是为了防止有人决定使用 PVS-Studio 测试源代码示例,将其排除在外。当他看到两个警告时,这个人会感到惊讶,尽管讨论的是只有一个。