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

喜夏-厌秋 提交于 2021-02-04 16:22:08

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!