For the following code
#include <bits/stdc++.h>
using namespace std;
int main()
{
bitset<64>b(numeric_limits<long>::min());
string s=b.to_string();
char *ptr=new char [s.size()+1];
strcpy(ptr,s.c_str());
long l1=strtol(ptr,NULL,2);
cout<<"l1= "<<l1<<endl;
long l2=strtoul(ptr,NULL,2);
cout<<"l2= "<<l2<<endl;
cout<<strtoul(ptr,NULL,2)<<endl;
}
The output is
l1= 9223372036854775807
l2= -9223372036854775808
9223372036854775808
Why is l1
not long_min
and why is l2
? I've read that the string can contain +
/-
sign in the beginning for ato*,strto* functions. But negative numbers in binary don't have any -
sign in 2's complement that computer uses. I'm confused.
The unsigned long int
value
9223372036854775808
outputted by this statement
cout<<strtoul(ptr,NULL,2)<<endl;
can not be represented in an object of the type signed long int
.
In this statement
long l1=strtol(ptr,NULL,2);
as the value is not representable in the type signed long int
the function strtol
returns LONG_MAX
(because there is no minus sign in the string). And this value is outputted by this statement
cout<<"l1= "<<l1<<endl;
From the C Standard (7.22.1.4 The strtol, strtoll, strtoul, and strtoull functions)
8 The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
However the value is representable as an unsigned long int
. So this call of the function strtoul
returns the correct value
long l2=strtoul(ptr,NULL,2);
but the value is assigned to an object of the type signed long int
. So its most significant bit is interpreted as the sign bit and the next statement
cout<<"l2= "<<l2<<endl;
outputs the value LONG_MIN
.