comparison between signed and unsigned integer

Hi, I am running a very small program and I am getting the warning "comparison between signed and unsigned integer expressions". Everything I read just says you should assign the value to an unsigned, but doesnt actually explain why, and I do not understand.
If someone could explain this, I would help greatly. Thank you

Code with warning.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  // Example program
#include <iostream>
#include <string>

using namespace std;

int wordCount(string input);

int main()
{
  string input;
  input = "The quick brown fox jumps over the lazy dog";
    wordCount(input);
}

int wordCount(string input)
{
    int spaces = 0; 
    for ( int i = 0; i < input.length(); i++)
  {
    if (input.substr(i,1) == " " ) 
    {
        spaces++;
    }   
  }
   cout << spaces;
}


Code without warning

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Example program
#include <iostream>
#include <string>

using namespace std;

int wordCount(string input);

int main()
{
  string input;
  input = "The quick brown fox jumps over the lazy dog";
    wordCount(input);
}

int wordCount(string input)
{
    int spaces = 0; 
    for (unsigned int i = 0; i < input.length(); i++)
  {
    if (input.substr(i,1) == " " ) 
    {
        spaces++;
    }   
  }
   cout << spaces;
}
Don't worry about the WARNING of unsigned vs signed integers. No problems here.

DO worry about the warning you didn't mention - function wordCount() doesn't return the int that it promised in its declaration.


What is the exact error/warning you are getting?

The warning should tell you what line of code is the problem.

I can make a guess what the offending line of code is.

Line 19, correct?

What is the return type of a string's length/size function?

size_t. size_t is an unsigned integral type (the same as member type string::size_type).

http://www.cplusplus.com/reference/string/string/length/
Note also that you do use the 'i' in string::substr() http://www.cplusplus.com/reference/string/string/substr/
that takes unsigned parameters.

The reason for the warning is that the result could surprise:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

int main()
{
    int x = -1;
    size_t y = 1;
    if ( x < y ) // warning: .. [-Wsign-compare]
      std::cout << "yes\n";
    else
      std::cout << "no\n";
}

no

That says that "no", the -1 is not less than +1.

The position and length of string are unsigned, because (a) negative values would not be logical and (b) unsigned ints can index longer arrays than signed.


You should not cout anything in your wordCount(). Just compute and return an answer. That way the function is more reusable. Let the caller decide what they do with the number.
I hope this doesn't diverge the thread too much, but note that Stroustrup basically said that unsigned container sizes were a mistake.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1428r0.pdf

C++20 introduces std::ssize to easily give a signed version of the container size.
https://en.cppreference.com/w/cpp/iterator/size
...but C++20 isn't actually released yet so you'll have to wait a bit. For now, just make i be size_t, or cast the .size() call to a [signed] int to avoid the warning.
Last edited on
@Ganado, thanks for sharing that paper. I've been looking for a good run-down on that problem for some time now.
Last edited on
Topic archived. No new replies allowed.