Warning - comparison between signed and unsigned integer expressions

I am currently working with accelerated C ++ and have encountered a problem in Exercise 2-3.

A brief overview of the program - the program basically takes a name and then displays a greeting in a star frame - i.e. Hello! surrounded by frames *.

Exercise . In the sample program, authors use const int to determine the filling (spaces) between the greeting and the asterisks. They then ask the reader, as part of the exercise, to ask the user to enter information about how big they want the pad to be.

All this seems quite simple, I suggest the user two integers ( int ) and save them and change the program to use these integers, deleting those used by the author during compilation, although I get the following warning;

Exercise2-3.cpp: 46: warning: comparing signed and unsigned expressions

After some research, it seems that this is because the code is trying to compare one of the above integers ( int ) with string::size_type , which is good. But I was wondering - does this mean that I have to change one of the integers to unsigned int ? Is it important to explicitly indicate whether my integers are signed or not?

  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 

The corresponding bits of code are indicated above, c is of type string::size_type , because we do not know how long the greeting can be - but why am I getting this problem now that the author code has not received the problem when using const int ? Also, for anyone who could complete Accelerated C ++, would this be explained later in the book?

I'm on Linux Mint using g ++ via Geany if that helps or matters (as I read that he could determine what string::size_type ).

+60
c ++ unsigned-integer
Sep 07 '10 at 17:06
source share
6 answers

It is generally recommended that variables be declared unsigned or size_t if they are compared with sizes to avoid this problem. If possible, use the exact type you will be comparing (for example, use std::string::size_type when comparing with the length of std::string ).

Compilers give warnings about comparing signature types and unsigned, because the ranges of signed and unsigned ints are different, and when they are compared with each other, the results may be unexpected. If you need to make such a comparison, you should explicitly convert one of the values ​​to a type compatible with the other, perhaps after checking to make sure 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(); } 
+84
Sep 07 '10 at 17:09
source share

I had the same problem that worked on problem 2-3 in Accelerated C ++ yesterday. The key is to change all the variables that you will be comparing (using logical operators) for compatible types. In this case, it means string::size_type (or unsigned int , but since this example uses the first one, I just stick with it, although both are technically compatible).

Note that in their source code they did just that for the c counter (page 30 in Section 2.5 of the book), as you correctly pointed out.

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

In your example, the code you posted will look 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 

Note that in the previous conditional expression you would get an error if you had not initialized the variable r as string::size_type in the for loop. Therefore, 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, as soon as you string::size_type variable string::size_type into the mix, anytime you want to perform a logical operation on this element, all operands must have a compatible type for compilation without warning.

+7
Jan 07 '14 at 16:25
source share

In extreme ranges, an unsigned int can become larger than an int.
Therefore, the compiler generates a warning. If you are sure that this is not a problem, feel free to apply the types to the same type so that the warning disappears (use C ++ so that they are easily recognized).

Alternatively, make variables of the same type to stop the compiler from complaining.
I mean, is it possible to have a negative complement? If so, save it as an int. Otherwise, you should probably use unsigned int and let the thread catch situations where the user enters a negative number.

+4
Sep 07 '10 at 17:13
source share

An important distinction between signed and unsigned ints is the interpretation of the last bit. The last bit in signed types denotes the sign of a number, which means: for example:

0001 - 1 signature and unsigned 1001 - -1 and 9 unsigned

(I avoided the whole complement problem for clarity of explanation! This is not quite how ints are represented in memory!)

You can imagine that it matters to know whether you are comparing with -1 or +9. In many cases, programmers are just too lazy to declare an int count to be unsigned (inflating the header of the fi loop) This is usually not a problem because with ints you have to count to 2 ^ 31 until your bit sign bites you. That is why this is just a warning. Because we are too lazy to write "unsigned" instead of "int".

+4
Sep 07 '10 at 17:32
source share

or use this header library and write:

 // |notEqaul|less|lessEqual|greater|greaterEqual if(sweet::equal(valueA,valueB)) 

and do not care about signed / unsigned or different sizes

0
Apr 09 '15 at 11:23
source share

The main problem is that the basic equipment, the central processor, has only instructions for comparing two signed values ​​or comparing two unsigned values. If you pass an unsigned comparison instruction a negative value with a sign, it will be perceived as a large positive number. Thus, -1, a bit combination with all bits (addition to two), becomes the maximum unsigned value for the same number of bits.

8 bits: -1 with a sign matches 255 unsigned 16-bit: -1 with a sign matches 65535 unsigned, etc.

So, if you have the following code:

 int fd; fd = open( .... ); int cnt; SomeType buf; cnt = read( fd, &buf, sizeof(buf) ); if( cnt < sizeof(buf) ) { perror("read error"); } 

you will find that if the read (2) call fails due to the file descriptor becoming invalid (or due to some other error), cnt will be set to -1. When comparing with sizeof (buf), an unsigned value, the if () operator will be false, because 0xffffffff is no less than sizeof () for some (reasonable, not invented to be the maximum size) data structure.

Thus, you should write above if, in order to remove a signed / unsigned warning like:

 if( cnt < 0 || (size_t)cnt < sizeof(buf) ) { perror("read error"); } 

It just speaks loudly about the problems.

 1. Introduction of size_t and other datatypes was crafted to mostly work, not engineered, with language changes, to be explicitly robust and fool proof. 2. Overall, C/C++ data types should just be signed, as Java correctly implemented. 

If you have values ​​so large that you cannot find a working type of signed value, you are using a processor too small or too large a value in your language. If, as is the case with money, each number matters, most languages ​​have systems that provide you with infinite numbers of accuracy. C / C ++ just doesn’t do very well, and you have to be very frank about types as mentioned in many other answers here.

0
Jul 15 '19 at 16:07
source share



All Articles