9
votes

The following C++ program calls strtoul of negative 1. Since no negative numbers are representable in any unsigned type, I had expected this to fail and return 0

If no valid conversion could be performed, a zero value is returned.

but instead a large positive number is returned

If the value read is out of the range of representable values by an unsigned long int, the function returns ULONG_MAX (defined in <climits>), and errno is set to ERANGE.

#include <cstdlib>
#include <iostream>

int main () {
  {char s[] = "-1";
    for (int b=0; b<17; ++b)
      std::cout << "strtoul (unsigned) of " << s
                << " with base arg " << b
                << ": " << strtoul(s,0,b) << std::endl;}
}

Why does strtoul not fail and return 0 for negative numbers?

3
What's your OS? Compiler? C/C++ runtime?Andrew Henle
@AndrewHenle. Irrelavant in this case. The function demonstrates correct behavior.Mad Physicist
@Galik. Not true. It only returns unsigned numbers.Mad Physicist
@MadPhysicist The function demonstrates correct behavior. That would depend on the value of the "large positive number" returned.Andrew Henle
@AndrewHenle. Technically true. I meant that in the sense that the OP has not described any unexpected behavior. If he listed a specific number that was not a power of 2 minus 1 for example, I would be more surprised.Mad Physicist

3 Answers

5
votes

You better use cppreference.com for documentation it seems to be much more accurate:

if the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules.

and as mentioned there optional plus or minus sign is a valid symbol

2
votes

Per the POSIX standard:

Since 0, {ULONG_MAX}, and {ULLONG_MAX} are returned on error and are also valid returns on success, an application wishing to check for error situations should set errno to 0, then call strtoul() or strtoull(), then check errno.

You need to check errno.

0
votes

From a different reference: cppreference.com:

Return value

Integer value corresponding to the contents of str on success. If the converted value falls out of range of corresponding return type, range error occurs and ULONG_MAX or ULLONG_MAX is returned. If no conversion can be performed, ​0​ is returned.

Which is apparently different than cplusplus.com