What is wrong with my For loops? I get warnings: comparison between signed and unsigned integer expressions [-Wsign-compare]

#include <iostream> #include <string> #include <vector> #include <sstream> using namespace std; int main() { vector<double> vector_double; vector<string> vector_string; ... while (cin >> sample_string) { ... } for(int i = 0; i <= vector_string.size(); i++) { .... } for (int i = 0; i < vector_double.size(); i++) .... return 0; } 
+7
source share
10 answers

Why is there a warning with -Wsign-compare ?

As the name of the warning and its text indicate, the problem is that you are comparing an integer with a signature and an unsigned one. It is generally considered to be an accident.

To avoid this warning, you just need to make sure that both operands of < (or any other comparison operator) are either signed or both unsigned.

How could I do better?

The idiomatic way to write a for loop is to initialize both the counter and the limit in the first statement:

 for (std::size_t i = 0, max = vec.size(); i != max; ++i) 

This saves recomputing size() at each iteration.

You can also (and probably should) use iterators instead of indexes:

 for (auto it = vec.begin(), end = vec.end(); it != end; ++it) 

auto here is an abbreviation for std::vector<int>::iterator . Iterators work for any containers, while indexes restrict you to C-arrays, deque and vector .

+13
source

This is because the .size () function from a vector class does not have an int type, but a vector :: size_type type

Use this or auto i = 0u , and the messages should disappear.

+5
source

int signed by default - this is equivalent to writing signed int . The reason you get the warning is because size() returns vector::size_type , which is more than likely unsigned.

This is a potential danger because signed int and unsigned int have different ranges of values. signed int can contain values ​​from –2147483648 to 2147483647 , and unsigned int can contain values ​​between 0 - 4294967295 (assuming int is 32 bits).

+3
source

Your variable i is an integer, and the member function of the vector size that returns Allocator::size_type most likely returns size_t , which is almost always implemented as an unsigned int of some size.

+2
source

Make your int i like size_type i .
std::vector::size() will return size_type , which is unsigned int since the size cannot be -ve.
The warning is obviously due to the fact that you are comparing a signed integer with an unsigned integer.

+2
source

Answering many answers, but no one noticed the end of the cycle. So here is my complete answer:

  • To remove the warning, change type i to unsigned , auto (for C ++ 11) or std::vector< your_type >::size_type
  • Your for loops will be seg-fault if you use this i as an index - you should loop from 0 to size-1 inclusive. So change this to be for( std::vector< your_type >::size_type i = 0; i < vector_xxx.size(); ++i )
    (pay attention to < , not <= ; my advice should not use <= with .begin() - 1 , because you may have a vector of size 0, and you will have problems with this :)).
  • To make this more universal, since you are using a container and you are repeating it, you can use iterator s. This will simplify the future change of container type (unless, of course, you need an exact position as a number). So, I would write it like this:

 for( std::vector< your_type >::iterator iter = vector_XXX.begin(); iter != vector_XXX.end(); ++iter ) { //.. } 
+2
source

You will get this warning because the size of the container in C ++ is an unsigned type, and mixing signature / unsigned types is dangerous.

What do i usually do

 for (int i=0,n=v.size(); i<n; i++) .... 

this is, in my opinion, the best way to use indexes, because using an unsigned type for an index (or container size) is a logical mistake.

Unsigned types should only be used when you care about bit representation and when you intend to use modulo- (2 ** n) overflow behavior. Using unsigned types just because the value is never negative is nonsense.

A typical mistake of using unsigned types for sizes or indexes is, for example,

 // Draw all lines between adjacent points for (size_t i=0; i<pts.size()-1; i++) drawLine(pts[i], pts[i+1]); 

the code above is UB when the array of points is empty, because in C ++ 0u-1 there is a huge positive number.

The reason C ++ uses an unsigned type for container size is because this choice is a historical legacy from 16-bit computers (and IMO, given the semantics of C ++ with unsigned types, it was the wrong choice even then).

+2
source

The declaration 'size_t i' works well for me.

+1
source

I usually solve it like this:

 for(int i = 0; i <= (int)vector_string.size(); i++) 

I use C-style because it is shorter and more readable than C ++ static_cast<int>() and does the same.

There is potential for overflow, but only if the size of your vector is larger than the largest int , as a rule, 2147483647. I have never had such a large vector in my life. If even the remote possibility of using a larger vector, one of the answers suggesting size_type would be more appropriate.

I'm not worried about calling size() repeatedly in a loop, since it is probably inline access to a member variable that does not incur overhead.

+1
source
 std::cout << -1U << std::endl; std::cout << (unsigned)-1 << std::endl; 4294967295 std::cout << 1 << std::endl; std::cout << (signed)1 << std::endl; 1 std::cout << (unsigned short)-1 << std::endl; 65535 std::cout << (signed)-1U << std::endl; std::cout << (signed)4294967295 << std::endl; -1 

unsubscribe your index variable

 unsigned int index; index < vecArray.size() // size() would never be negative 
0
source

All Articles