1

My code

#include <stdio.h>
#include<bits/stdc++.h>
using namespace std;
int main()
{
    vector<int> nums;
    cout<<"size="<<nums.size()<<"\n";
    cout <<"diff1 = "<<0-2<<"\n";
    cout<<"diff2 = "<<nums.size()-2<<"\n";
    return 0;
}

Output

size=0
diff1 = -2
diff2 = 18446744073709551614

Expected output diff2 = -2 Not sure how this output is getting generated. I haven't seen this type of behavior.

Abhilasha
  • 357
  • 1
  • 5
  • 19
  • 8
    It's because size() return a size_t (unsigned type). – MatthieuL Jul 08 '20 at 06:29
  • Do you know about integer over/underflow? – RoQuOTriX Jul 08 '20 at 06:29
  • 1
    Unrelated and maybe you didn't know it, but you included the _whole_ standard library in this small example for no reason. You might want to read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Lukas-T Jul 08 '20 at 06:32
  • 2
    This is actually well defined behaviour, not undefined behaviour. Obviously it's surprising behaviour for you, but that doesn't mean its undefined. – john Jul 08 '20 at 06:35
  • Thanku everyone, I missed this crucial info. – Abhilasha Jul 08 '20 at 09:03
  • @churill Thanks for including additional info Will keep this mind – Abhilasha Jul 08 '20 at 09:05

3 Answers3

4

nums.size() returns an unsigned type (actually size_t). Unsigned types have a smallest possible value of zero, so there's an issue when you try to generate a negative unsigned value. What the standard says is that the value wraps around. So a value of -1 converted to an unsigned type is the largest value that unsigned type can have, and similarly a value of -2 would be the second largest value that unsigned type can have.

That's what you are seeing in your output.

john
  • 85,011
  • 4
  • 57
  • 81
  • strictly speaking, the type is a `std::vector::size_type` which, indeed has to be `unsigned`, but might not be `size_t`. – Bathsheba Jul 08 '20 at 06:49
  • @Bathsheba I thought that unless you had a custom allocator `size_type` had to be `size_t`. That was the case in C++98 but I've not kept up with developments since then, – john Jul 08 '20 at 06:57
2

No the behaviour is not undefined.

It's just that nums.size() is an unsigned type (formally a std::vector<int>::size_type), and the expression num.size() - 2 is evaluated in unsigned arithmetic due to the rules of implicit conversions. -1 in this case is std::numeric_limits<std::vector<int>::size_type>::max() and -2 is one less than that, which accounts for your output (264 - 2). This wrap-around behaviour of unsigned arithmetic is defined by the C++ standard.

As a rule of thumb, using negatives in unsigned arithmetic is best avoided.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1
 (nums.size()-2 ) will be unsigned why because nums.size() is unsigned.

and this will lead to below operator function of ostream

basic_ostream& operator<<( unsigned int value ); 

that's why you have unsigned result. if you want to see -2 then cast num.size() as int ((int)nums.size()-2) will result -2

more detail you can check https://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt

Nilesh Solanki
  • 336
  • 4
  • 19