问题
What should I do about the "signed/unsigned mismatch" warning in C++ code like this:
for (int i = vector.size() - 1; i >= 0; --i) // OK
{
if (i < vector.size() / 2) // warning C4018: '<': signed/unsigned mismatch
// ...
}
(A contrived example, but it demonstrates the problem.)
How do I deal with "signed/unsigned mismatch" warnings (C4018)? says to use size_t
for the loop variable, but this doesn't work for a decrementing loop terminating at 0. It compiles without warning, but the integer overflows (or is it underflows?) at runtime and becomes 4294967295.
回答1:
Firstly, learn a few well-established idioms that'd allow you to write decrementing cycles using unsigned
types. This is an absolutely essential skill in C and C++. E.g.
for ([some unsigned type] i = N; i-- > 0; )
{
// Process i-th element
}
or
for ([some unsigned type] i = N; i > 0; )
{
--i;
// Process i-th element
}
(Note, that the initial value of i
is N
, not N - 1
.)
Or you can even use a "more natural" approach
for ([some unsigned type] i = N - 1; i != -1; --i)
{
// Process i-th element
}
Secondly, start using the proper unsigned type for vector indexing. In your case
for (auto i = vector.size() - 1; i != -1; --i)
or
for ([your vector type]::size_type i = vector.size() - 1; i != -1; --i)
That will solve your warning issue.
Alternatively, you can choose a "loser's way out" and just suppress the warning by using an explicit cast
if ((unsigned) i < vector.size() / 2)
or just do #pragma warning(disable: 4018)
.
回答2:
There are several options you could do:
If you use a vector use an iterator for traversing it:
for (auto it = vector.rbegin(); it != vector.rend(); ++it)
Or use a different for statement:
for (size_t i = vector.size(); i-- > 0; )
I also have seen for(size_t i = myArray.size() - 1; i != (size_t)-1; i--)
(cf. What's the best way to do a backwards loop in C/C#/C++?)
回答3:
or alternatively:
for(size_t j = 0; j < vector.size(); j++){
size_t i = vector.size() - 1 - j;
...
}
回答4:
Use the proper type (auto
, std::size_t
, std::vector<...>::size_type
) and iterate from vector.size()
down to 0
(and not from vector.size() - 1
down to -1
) instead:
for (std::size_t i = vector.size(); i > 0; --i)
{
if (i < vector.size() / 2 + 1)
// ...
}
回答5:
Me I would write an index range-for adapter.
And write backwards, which adapts a range to iterate in reverse.
This gives us:
for(auto i:backwards(indexes_into(container))){
the result is less error prone, as efficient, and clearer intention at point of use (so long as you trust your utility code).
Solutions to both exist in boost, rangesv3, and various of my SO posts.
来源:https://stackoverflow.com/questions/38945669/signed-unsigned-mismatch-warnings-c4018-with-decrementing-for-loop