It sounds like a long
on your system is a 32-bit value. That means any unsigned number above 4,294,967,295 won't convert correctly, and neither will signed numbers above 2,147,483,647 or below 2,147,483,648.
In general, an n-bit representation can represent signed numbers in the range [-2n-1,-2n-1) or unsigned numbers in the range [0,2n).
The wikipedia article Computer numbering formats is probably a good jumping off point to learn more about this behaviour.
The reason you see different results from atol()
and strtol()
is because they have different error handling characteristics. From the strtol()
man page:
The strtol()
function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol()
returns LONG_MIN
. If an overflow occurs, strtol()
returns LONG_MAX
. In both cases, errno
is set to ERANGE
.
And from the atol()
man page:
The atoi()
function converts the initial portion of the string pointed to by nptr
to int. The behaviour is the same as
strtol(nptr, (char **)NULL, 10);
except that atoi()
does not detect errors.
The atol()
and atoll()
functions behave the same as atoi()
, except that they convert the initial portion of the string to their return type of long
or long long
.