EM0
EM0

Reputation: 6337

“signed/unsigned mismatch” warnings (C4018) with decrementing for loop

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.

Upvotes: 2

Views: 2936

Answers (5)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275600

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.

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320571

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).

Upvotes: 7

ewcz
ewcz

Reputation: 13087

or alternatively:

for(size_t j = 0; j < vector.size(); j++){
    size_t i = vector.size() - 1 - j;
    ...
}

Upvotes: 1

MrTux
MrTux

Reputation: 34002

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++?)

Upvotes: 3

mike.dld
mike.dld

Reputation: 3049

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)
        // ... 
}

Upvotes: 0

Related Questions