I'm facing a little problem and I hope you can help me. Thank you.
Here is the error code:
FILE.cpp: In member function 'bool DragonSoulTable::ReadAdditionalApplys()':
FILE.cpp:223: warning: comparison between signed and unsigned integer expressions
And here is the code I put on pastebin because it is too big to put that code on forum
FILE.CPP
Go to line 223, you have:
for (int i = 0; i < m_vecDragonSoulNames.size(); i++)
As you can see, i is of type int but does m_vecDragonSoulNames.size() return an int??
In fact, you have a lot of comparisons like this in your code.
Compilers give warnings (not errors) when you compare signed and unsigned types, this is because the ranges of this types are different. And there are good reasons for this, if you dont be careful the results can be surprising...
If you know its safe to make such a comparison, you can explicitly cast one of the values to be of the same type of the other, and the warning will dissapear.
Something like:
unsigned int a = someUnisgnedValue;
int b = someSignedValue;
if ((unsigned) b < a)
//... do something
Or you can just use both of the same type. For example in the line 223 of your code you can do:
for (unsigned int i = 0; i < m_vecDragonSoulNames.size(); i++)
Please, check this other question: When to use unsigned values over signed ones?
Exactly what the warning says. You are comparing signed and unsigned integers. For example:
uint NUM = 5;
for (int i=0; i < NUM; i++) // Here you compare int and uint
The solution is to
make all of your variable the same type,
disregard the warning
suppress it
compile with lower error reporting level and thus not generate it at all.
In that for loop i is integer where as the m_vecDragonSoulNames.size() is of type unsigned integer. make i unsigned int
Related
auto.cpp: In function ‘int autooo(unsigned int)’:
auto.cpp:33:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
im doing the makefile , and i already run the makefile and make an auto.o but still i get this error, below is my autooo.cpp , auto.h
i dont undestand what is unsigned and signed :\ please help
auto.h
#ifndef function_H_
#define function_H_
int autooo(unsigned);
int interr(unsigned);
#endif /* function_H_ */
autooo.cpp
#include <iostream>
#include <cstdlib> //for random functions
#include "prime.h"
#include "auto.h"
using namespace std;
#ifndef auto_CPP_
#define auto_CPP_
int autooo(unsigned);
int autooo(unsigned a)
{
int b=50;
unsigned numberFound = 0;
do
{
++a;
if (isPrime(a))
{
++numberFound;
cout << a << "is prime number" <<endl;
}
} while (numberFound < b);
return 0;
}
#endif
The compiler warns that the code contains comparison of unsigned int with a signed int in the line
while (numberFound < b);
This has nothing to do with makefiles or make.
You can fix that by changing
int b=50;
to
unsigned b = 50;
or by changing
unsigned numberFound = 0;
to
int numberFound = 0;
The problems you might run into when comparing signed int and unsigned int are explained in this answer to another SO question
At this line
while (numberFound < b);
The first is an unsigned int and the second an int. So you have to make them the same type, or if you are completely sure cast one of them.
As Etan commented:
"Blindly casting away a warning just to avoid the warning is a mistake. You need to understand what the warning is telling you and decide what the right fix is."
You are getting this warning about comparing signed and unsigned types because the ranges of signed and unsigned ints are different.
If you have to make such a comparison, you should explicitly cast one of the values to be compatible with the other, but a check is required to make sure value your cast is valid.
For e.g:-
int i = someIntValue();
if (i >= 0)
{
// i is non-negative, so it is safe to compare to unsigned value
if ((unsigned)i >= u)
// do something
}
It says you are comparing two different things. Most notably the range of one does not fit into the range of another.
I.e there. Exists a number in the unsigned range that cannot be expressed as a signed number
Type cast the code before you were comparing the signed and unsigned code to avoid warning
int a;
unsigned int b;
if(a==b) gives warning
if(a == (int)b)
will resolve your issue
EDIT
Blind casting will lead to some unexpected results
The warning is because ranges for signed and unsigned are different.
Casting will work fine when signed integer you were used for comparison was greater than zero.
so have check whether the signed integer is greater that zero before comparing
More info here
auto.cpp: In function ‘int autooo(unsigned int)’:
auto.cpp:33:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
im doing the makefile , and i already run the makefile and make an auto.o but still i get this error, below is my autooo.cpp , auto.h
i dont undestand what is unsigned and signed :\ please help
auto.h
#ifndef function_H_
#define function_H_
int autooo(unsigned);
int interr(unsigned);
#endif /* function_H_ */
autooo.cpp
#include <iostream>
#include <cstdlib> //for random functions
#include "prime.h"
#include "auto.h"
using namespace std;
#ifndef auto_CPP_
#define auto_CPP_
int autooo(unsigned);
int autooo(unsigned a)
{
int b=50;
unsigned numberFound = 0;
do
{
++a;
if (isPrime(a))
{
++numberFound;
cout << a << "is prime number" <<endl;
}
} while (numberFound < b);
return 0;
}
#endif
The compiler warns that the code contains comparison of unsigned int with a signed int in the line
while (numberFound < b);
This has nothing to do with makefiles or make.
You can fix that by changing
int b=50;
to
unsigned b = 50;
or by changing
unsigned numberFound = 0;
to
int numberFound = 0;
The problems you might run into when comparing signed int and unsigned int are explained in this answer to another SO question
At this line
while (numberFound < b);
The first is an unsigned int and the second an int. So you have to make them the same type, or if you are completely sure cast one of them.
As Etan commented:
"Blindly casting away a warning just to avoid the warning is a mistake. You need to understand what the warning is telling you and decide what the right fix is."
You are getting this warning about comparing signed and unsigned types because the ranges of signed and unsigned ints are different.
If you have to make such a comparison, you should explicitly cast one of the values to be compatible with the other, but a check is required to make sure value your cast is valid.
For e.g:-
int i = someIntValue();
if (i >= 0)
{
// i is non-negative, so it is safe to compare to unsigned value
if ((unsigned)i >= u)
// do something
}
It says you are comparing two different things. Most notably the range of one does not fit into the range of another.
I.e there. Exists a number in the unsigned range that cannot be expressed as a signed number
Type cast the code before you were comparing the signed and unsigned code to avoid warning
int a;
unsigned int b;
if(a==b) gives warning
if(a == (int)b)
will resolve your issue
EDIT
Blind casting will lead to some unexpected results
The warning is because ranges for signed and unsigned are different.
Casting will work fine when signed integer you were used for comparison was greater than zero.
so have check whether the signed integer is greater that zero before comparing
More info here
in c++, is it okay to compare an int to a char because of implicit type casting? Or am I misunderstanding the concept?
For example, can I do
int x = 68;
char y;
std::cin >> y;
//Assuming that the user inputs 'Z';
if(x < y)
{
cout << "Your input is larger than x";
}
Or do we need to first convert it to an int?
so
if(x < static_cast<int>(y))
{
cout << "Your input is larger than x";
}
The problem with both versions is that you cannot be sure about the value that results from negative/large values (the values that are negative if char is indeed a signed char). This is implementation defined, because the implementation defines whether char means signed char or unsigned char.
The only way to fix this problem is to cast to the appropriate signed/unsigned char type first:
if(x < (signed char)y)
or
if(x < (unsigned char)y)
Omitting this cast will result in implementation defined behavior.
Personally, I generally prefer use of uint8_t and int8_t when using chars as numbers, precisely because of this issue.
This still assumes that the value of the (un)signed char is within the range of possible int values on your platform. This may not be the case if sizeof(char) == sizeof(int) == 1 (possible only if a char is 16 bit!), and you are comparing signed and unsigned values.
To avoid this problem, ensure that you use either
signed x = ...;
if(x < (signed char)y)
or
unsigned x = ...;
if(x < (unsigned char)y)
Your compiler will hopefully complain with warning about mixed signed comparison if you fail to do so.
Your code will compile and work, for some definition of work.
Still you might get unexpected results, because y is a char, which means its signedness is implementation defined. That combined with unknown size of int will lead to much joy.
Also, please write the char literals you want, don't look at the ASCII table yourself. Any reader (you in 5 minutes) will be thankful.
Last point: Avoid gratuituous cast, they don't make anything better and may hide problems your compiler would normally warn about.
Yes you can compare an int to some char, like you can compare an int to some short, but it might be considered bad style. I would code
if (x < (int)y)
or like you did
if (x < static_cast<int>(y))
which I find a bit too verbose for that case....
BTW, if you intend to use bytes not as char consider also the int8_t type (etc...) from <cstdint>
Don't forget that on some systems, char are signed by default, on others they are unsigned (and you could explicit unsigned char vs signed char).
The code you suggest will compile, but I strongly recommend the static_cast version. Using static_cast you will help the reader understand what do you compare to an integer.
In a lot of code examples, source code, libraries etc. I see the use of int when as far as I can see, an unsigned int would make much more sense.
One place I see this a lot is in for loops. See below example:
for(int i = 0; i < length; i++)
{
// Do Stuff
}
Why on earth would you use an int rather than an unsigned int? Is it just laziness - people can't be bothered with typing unsigned?
Using unsigned can introduce programming errors that are hard to spot, and it's usually better to use signed int just to avoid them. One example would be when you decide to iterate backwards rather than forwards and write this:
for (unsigned i = 5; i >= 0; i--) {
printf("%d\n", i);
}
Another would be if you do some math inside the loop:
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
if (i - j >= 4) printf("%d %d\n", i, j);
}
}
Using unsigned introduces the potential for these sorts of bugs, and there's not really any upside.
It's generally laziness or lack of understanding.
I aways use unsigned int when the value should not be negative. That also serves the documentation purpose of specifying what the correct values should be.
IMHO, the assertion that it is safer to use "int" than "unsigned int" is simply wrong and a bad programming practice.
If you have used Ada or Pascal you'd be accustomed to using the even safer practice of specifying specific ranges for values (e.g., an integer that can only be 1, 2, 3, 4, 5).
If length is also int, then you should use the same integer type, otherwise weird things happen when you mix signed and unsigned types in a comparison statement. Most compilers will give you a warning.
You could go on to ask, why should length be signed? Well, that's probably historical.
Also, if you decide to reverse the loop, ie
for(int i=length-1;i>=0 ;i--)
{
// do stuff
}
the logic breaks if you use unsigned ints.
I chose to be as explicit as possible while programming. That is, if I intend to use a variable whose value is always positive, then unsigned is used. Many here mention "hard to spot bugs" but few give examples. Consider the following advocate example for using unsigned, unlike most posts here:
enum num_things {
THINGA = 0,
THINGB,
THINGC,
NUM_THINGS
};
int unsafe_function(int thing_ID){
if(thing_ID >= NUM_THINGS)
return -1;
...
}
int safe_function(unsigned int thing_ID){
if(thing_ID >= NUM_THINGS)
return -1;
...
}
int other_safe_function(int thing_ID){
if((thing_ID >=0 ) && (thing_ID >= NUM_THINGS))
return -1;
...
}
/* Error not caught */
unsafe_function(-1);
/* Error is caught */
safe_function((unsigned int)-1);
In the above example, what happens if a negative value is passed in as thing_ID? In the first case, you'll find that the negative value is not greater than or equal to NUM_THINGS, and so the function will continue executing.
In the second case, you'll actually catch this at run-time because the signedness of thing_ID forces the conditional to execute an unsigned comparison.
Of course, you could do something like other_safe_function, but this seems more of a kludge to use signed integers rather than being more explicit and using unsigned to begin with.
I think the most important reason is if you choose unsigned int, you can get some logical errors. In fact, you often do not need the range of unsigned int, using int is safer.
this tiny code is usecase related, if you call some vector element then the prototype is int but there're much modern ways to do it in c++ eg. for(const auto &v : vec) {} or iterators, in some calculcation if there's no substracting/reaching a negative number you can and should use unsigned (explains better the range of values expected), sometimes as many posted examples here shows you actually need int but the truth is it's all about usecase and situation, no one strict rule apply to all usecases and it would be kinda dumb to force one over...
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.....?
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.
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.
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 )
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;
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