Tomazi
Tomazi

Reputation: 791

C++ for loop structure

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

Answers (5)

Jon Purdy
Jon Purdy

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

Drew Dormann
Drew Dormann

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

Jean
Jean

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

Qortex
Qortex

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

John
John

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

Related Questions