Reputation: 791
Hope its not a lame question but I have to ask this :)
When I program in C++ and use for
loops the parameters I give are i.e.
for(int i = 0; i< something; i++)
Which is correct way forward but..this gives me compile warnings such as this:
1>c:\main.cpp(185): warning C4018: '<' : signed/unsigned mismatch
Now going through books and reading online most for loops examples are of this structure.
I was always ignoring warnings as my programs always worked and did what they suppose to do, until I got interested with this warnings and did a small research....by copying this Waring and Google it to find that it is better if I use this structure to avoid the warning:
for(vector<int>::size_type i= 0; i < something; i++ )
Now my question here is why......if the initial structure works and is described and documented in many books and online resources.
Also what is the benefit or is there any significant difference in the techniques.....?
Why would I use this
for(vector<int>::size_type i= 0; i < something; i++ )
apart from getting rid of the warnings.....?
Upvotes: 4
Views: 551
Reputation: 55079
Broadly, there are two kinds of integral types in C++: signed and unsigned. For each size of integer, there is a signed and an unsigned version. The difference is in their range: signed integers of n bits have a range from −2n − 1 to +2n − 1 − 1; unsigned integers, from 0 to 2n − 1.
When comparing signed integer types to unsigned, the signed value is converted to unsigned; negative values will wrap and be treated as large positive values. The upshot of this is that comparisons with <
might not do what you expect, so many compilers will warn about such comparisons.
For example, 1u < -1
is true. u
is a suffix that tells the compiler to treat the 1
as an unsigned int
value.
With that, the meaning becomes clear: int
is a signed type and vector<T>::size_type
is an unsigned type. Since the result of vector<T>::size()
is vector<T>::size_type
, you want to use that or another unsigned type such as size_t
to ensure that your comparisons have the behaviour you want.
Instead of using indices, you can also use iterators, which don’t have such conversion problems:
for (vector<int>::iterator i = v.begin(); i != v.end(); ++i)
cout << *i << '\n';
Which can be made more succinct with auto
in C++11:
for (auto i = v.begin(); i != v.end(); ++i)
cout << *i << '\n';
If you’re just iterating over the whole container, use C++11 range-based for
:
for (int i : v)
cout << i << '\n';
And if you want to modify the values, use a reference:
for (int& i : v)
++i;
Upvotes: 3
Reputation: 63945
Why would I use this
Because signed int
and unsigned values like size_t
have differing ranges, and you may not get your expected result if one contains a value that can not be represented by the other.
That said, if you think that code is too verbose, you don't have to use it.
Code like this:
for(vector<int>::size_type i= 0; i < myvector.size(); i++ )
{
int val = myvector[i];
Can also be written like this.
for ( int val : myvector )
Upvotes: 3
Reputation: 7673
something
must be int
, otherwise you get the warning. Or i
must be unsigned int
, depending on your needs.
Assuming a 32 bits integers, if signed any value above 0x7FFFFFFF
(2,147,483,647 decimal
) will be interpreted as negative, whereas it will be positive for an unsigned int
.
So the compiler is issuing a warning telling you that comparison mail result in unexpected outcome.
32 bits integers range from −2,147,483,648 to 2,147,483,647.
32 bits unsigned integers range from 0 to 4,294,967,295
Upvotes: 1
Reputation: 7466
You simply have a signed
/ unsigned
mismatch between the type of i
and the type of something
in your statement:
for(int i = 0; i < something; i++)
So this has nothing to do with the for
structure, but rather with the comparison.
bool b = i < something;
would give you the same warnings.
This can be the case if you use int i
and compare it to a size_t
variable somehow (which is what std::vector::size()
gives you).
So, to fix it, simply change your for
loop to using the same type for i
and for something
, such as:
for(size_t i = 0; i < something; i++)
if something
is of type size_t
.
Upvotes: 3
Reputation: 16007
Don't ignore the warnings. They're trying to tell you something.
I suspect something
is unsigned.
If you have
unsigned int something = 0;
something--; // Now something is a really large positive integer, not -1
If you ignore the warnings, and you don't have your compiler set to treat warnings as errors, then this will compile fine, but you won't get what you expect.
You're probably seeing that vector<int>::size_type
is an unsigned int
if the warning goes away.
Upvotes: 4