Reputation: 13
Let me start by saying: I'm sorry if this was explained, I tried reading about it and searching for answer but I didn't find one that answered this specific question.
So I'm writing beginner's level code in C++ and I wrote a very simple function that returns index of the next found character that isn't space. It was inspired by the method string.find(). If the function doesn't find anything it returns string::npos.
int findChar (const string &line, const int startPos){
for (unsigned int i= startPos; i < line.length(); i++){
if ( line[i] != ' ') return i;
}
return string::npos;
}
Now, because I'm working on strings and indices, I thought of using a unsigned int.
unsigned int where;
where = findChar(line, 0);
And because "where" is an unsigned int I thought comparison of "where == string::npos" is a bad idea because string::npos is initialized with -1, and unsigned int can't be equal to -1. But if the function doesn't find anything and it returns string::npos the condition can be true, the program recognizes that "unsigned int where" is string::npos, but when I try to print "where" out, it prints out as biggest number unsigned int can hold.
So my question is why, or how, the program can recognize unsigned int to be equal to string::npos, even though technically string::npos is initialized with value of -1.
I'm trying to learn so if you can point me to some reading material that also answers this I'd be grateful.
Upvotes: 0
Views: 854
Reputation: 141648
string::npos
is a large positive number .
To avoid these issues, your function's return type should match the type of the value you are returning, e.g.:
string::size_type
instead of int
, or:-1
in the first code.The way you have it now, there can always be a clash when the "adjusted" value to fit in the return type happens to be the same as a valid return value.
Although npos
might be initialized with -1
in an implementation header, that doesn't mean its value is -1
. The initializer is converted to the type of the object being initialized, which is string::size_type
, guaranteed to be an unsigned type. The result of this conversion is a large positive value.
NB. Your code will break miserably if called on a string longer than UINT_MAX
characters, since the i
loop never ends. The i
should also be string::size_type
rather than int
; and similar considerations apply to the startPos
parameter.
Upvotes: 1
Reputation: 211700
If you read the documentation:
Although the definition uses -1, size_type is an unsigned integer type, and the value of npos is the largest positive value it can hold, due to signed-to-unsigned implicit conversion. This is a portable way to specify the largest value of any unsigned type.
Note: std::string::npos
is of type size_t
. Using anything else may be undefined behaviour and is not advised.
Upvotes: 3