Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A warning - comparison between signed and unsigned integer expressions

I am currently working through Accelerated C++ and have come across an issue in exercise 2-3.

A quick overview of the program - the program basically takes a name, then displays a greeting within a frame of asterisks - i.e. Hello ! surrounded framed by *'s.

The exercise - In the example program, the authors use const int to determine the padding (blank spaces) between the greeting and the asterisks. They then ask the reader, as part of the exercise, to ask the user for input as to how big they want the padding to be.

All this seems easy enough, I go ahead ask the user for two integers (int) and store them and change the program to use these integers, removing the ones used by the author, when compiling though I get the following warning;

Exercise2-3.cpp:46: warning: comparison between signed and unsigned integer expressions

After some research it appears to be because the code attempts to compare one of the above integers (int) to a string::size_type, which is fine. But I was wondering - does this mean I should change one of the integers to unsigned int? Is it important to explicitly state whether my integers are signed or unsigned?

 cout << "Please enter the size of the frame between top and bottom you would like ";  int padtopbottom;  cin >> padtopbottom;   cout << "Please enter size of the frame from each side you would like: ";  unsigned int padsides;   cin >> padsides;   string::size_type c = 0; // definition of c in the program  if (r == padtopbottom + 1 && c == padsides + 1) { // where the error occurs 

Above are the relevant bits of code, the c is of type string::size_type because we do not know how long the greeting might be - but why do I get this problem now, when the author's code didn't get the problem when using const int? In addition - to anyone who may have completed Accelerated C++ - will this be explained later in the book?

I am on Linux Mint using g++ via Geany, if that helps or makes a difference (as I read that it could when determining what string::size_type is).

like image 754
Tim Harrington Avatar asked Sep 07 '10 17:09

Tim Harrington


People also ask

Can we compare signed and unsigned integer?

A 1-byte unsigned integer has a range of 0 to 255. Compare this to the 1-byte signed integer range of -128 to 127. Both can store 256 different values, but signed integers use half of their range for negative numbers, whereas unsigned integers can store positive numbers that are twice as large.

What is the difference between unsigned and signed?

The term "unsigned" in computer programming indicates a variable that can hold only positive numbers. The term "signed" in computer code indicates that a variable can hold negative and positive values.

What happen when a signed negative integer is compared with an unsigned integer?

If Data is signed type negative value, the right shifting operation of Data is implementation-dependent but for the unsigned type, it would be Data/ 2pos. If Data is signed type negative value, the left shifting operation of Data shows the undefined behavior but for the unsigned type, it would be Data x 2pos.

What is the difference between a signed number and an unsigned number?

Signed numbers use sign flag or can be distinguish between negative values and positive values. Whereas unsigned numbers stored only positive numbers but not negative numbers.


2 Answers

It is usually a good idea to declare variables as unsigned or size_t if they will be compared to sizes, to avoid this issue. Whenever possible, use the exact type you will be comparing against (for example, use std::string::size_type when comparing with a std::string's length).

Compilers give warnings about comparing signed and unsigned types because the ranges of signed and unsigned ints are different, and when they are compared to one another, the results can be surprising. If you have to make such a comparison, you should explicitly convert one of the values to a type compatible with the other, perhaps after checking to ensure that the conversion is valid. For example:

unsigned u = GetSomeUnsignedValue(); int i = GetSomeSignedValue();  if (i >= 0) {     // i is nonnegative, so it is safe to cast to unsigned value     if ((unsigned)i >= u)         iIsGreaterThanOrEqualToU();     else         iIsLessThanU(); } else {     iIsNegative(); } 
like image 81
Kristopher Johnson Avatar answered Sep 17 '22 14:09

Kristopher Johnson


I had the exact same problem yesterday working through problem 2-3 in Accelerated C++. The key is to change all variables you will be comparing (using Boolean operators) to compatible types. In this case, that means string::size_type (or unsigned int, but since this example is using the former, I will just stick with that even though the two are technically compatible).

Notice that in their original code they did exactly this for the c counter (page 30 in Section 2.5 of the book), as you rightly pointed out.

What makes this example more complicated is that the different padding variables (padsides and padtopbottom), as well as all counters, must also be changed to string::size_type.

Getting to your example, the code that you posted would end up looking like this:

cout << "Please enter the size of the frame between top and bottom"; string::size_type padtopbottom; cin >> padtopbottom;  cout << "Please enter size of the frame from each side you would like: "; string::size_type padsides;  cin >> padsides;  string::size_type c = 0; // definition of c in the program  if (r == padtopbottom + 1 && c == padsides + 1) { // where the error no longer occurs 

Notice that in the previous conditional, you would get the error if you didn't initialize variable r as a string::size_type in the for loop. So you need to initialize the for loop using something like:

    for (string::size_type r=0; r!=rows; ++r)   //If r and rows are string::size_type, no error! 

So, basically, once you introduce a string::size_type variable into the mix, any time you want to perform a boolean operation on that item, all operands must have a compatible type for it to compile without warnings.

like image 33
eric Avatar answered Sep 19 '22 14:09

eric