29

I'm doing two operations involving atoi and I'm wondering how I can do this with unsigned integers because atoi seems to convert these to signed causing a wraparound integer overflow. I want to work with 32bit unsigned integers but atoi is limiting me effectively to 31bit unsigned.

 if (multiplication_is_safe(atoi(argv[1]),atoi(argv[3])))
    {
     printf("%s * %s = %u \n", argv[1], argv[3], atoi(argv[1]) * atoi(argv[3]));
      return 0;
    }  else
John
  • 341
  • 1
  • 6
  • 13

2 Answers2

35

The simple answer is to use strtoul() instead.

The longer answer is that even if all you needed was signed 32 bit integers or were happy with 31 bits for unsigned, the atoi() function is a poor fit for what you appear to be doing.

As you have already noted, the atoi() function converts a string to an integer. A normal, signed integer. However, what atoi() doesn't do is error handling. What atoi()'s specification says is "If the value cannot be represented, the behavior is undefined."

The strto*() family of functions all clearly specify how errors are handled, so you should in all cases replace atoi() with calls to strtol() (convert string to long), and in this case since you want to handle unsigned integers, you should use strtoul() (convert string to unsigned long).

Also note that if you want to handle larger numbers, there are the strtoll() and strtoull() functions, to convert your string to a long long or an unsigned long long. (And if you just want to handle the largest possible integral values without bothering with all that stuff in between, there's strtoimax() and strtoumax(), that return values of type intmax_t or uintmax_t respectively.)

POSIX Documentation:

johnchen902
  • 9,531
  • 1
  • 27
  • 69
This isn't my real name
  • 4,869
  • 3
  • 17
  • 30
  • Great answer. Love the `undefined` quote. I hit this issue. I put a decimal value of ~7 billion (that fit nicely into an `unsigned long long`) into `atoi()`. I was hoping for an error code. Instead I got the MAX value for an `unsigned long long` . This value was 18 billion billion. – rustyMagnet Mar 14 '19 at 13:42
  • I really like this article from Microsoft on the limits of C Data Types `https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=vs-2017` Very relevant when dealing with `atoi` and the `int` return type. – rustyMagnet Mar 14 '19 at 13:44
2

Depending on your platform, strtoul is probably what you want:

The strtoul() function converts the initial part of the string in nptr to an unsigned long int value according to the given base, which must be between 2 and 36 inclusive, or be the special value 0.

The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134