I understand that s1.size() - s2.size() underflows when s2 is bigger because it's subtraction of unsigned.
Why casting one them to int doesn't result in integer subtraction?
Why casting the whole thing gives me the correct result? I expected it to evaluate what is inside parentheses, then underflow which would give a big number and then the cast to int would not make difference. What am I missing?
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
bool isShorter(const string &s1, const string &s2) {
return (static_cast<int>(s1.size()) - s2.size() < 0) ? true : false; // underflows
//return (static_cast<int>(s1.size() - s2.size()) < 0) ? true : false; // this works
}
int main() {
string s, t;
getline(cin, s);
getline(cin, t);
cout << "s: " << s << endl;
cout << "t: " << t << endl;
cout << "printing shorter string of the two..." << endl;
cout << ((isShorter(s, t)) ? s : t) << endl;
}
When you do
You convert
s1.size()to aintand then when you subtracts2.size()from it thatintis promoted to the same type ass2.size()and then it is subtracted. This means you still have unsigned integer subtraction and since that can't ever be negative it will wrap around to a larger number. It is no different from doings1.size() - s2.size().You have the same thing with
With the added bonus of possible signed integer overflow which is undefined behavior. You are still doing unsigned integer subtraction so if
s1is smaller thans2than you wrap around to a large number.What you need to do is convert both
s1.size()ands2.size()to a signed integer type to get singed integer subtraction. That could look likeAnd now you will actually get a negative number if
s1.size()is less thans2.size().It should be noted that all of this can be avoided by using less than operator. Your function can be rewritten to be
which, IMHO, is much easier to read and understand.