12

I read that atoi() is deprecated and that it is equivalent to:

(int)strtol(token_start, (char **)NULL, 10); 

Does that mean I should use the above instead of atoi(chr) or is it just saying they are equivalent?

2
  • 3
    My problem with atoi: assert( atoi("0") != atoi(!blah") ) Commented Sep 28, 2009 at 18:43
  • 3
    atoi is poor because it does almost no well-defined error detection, but even when using strtol, properly detecting (and classifying) errors is surprisingly difficult, and none of the answers here really addresses that. See the answers at this question for some guidance. Commented Jun 24, 2018 at 12:06

6 Answers 6

24

atoi is not deprecated, your source is incorrect. Nothing in the current C standard ISO 9899:2011 indicates this (see for example chapter 6.11 future language directions), nor anything in earlier standards.

As per the C standard, atoi is equivalent to strtol as follows, C11 7.22.1.2:

The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively.

Except for the behavior on error, they are equivalent to

atoi: (int)strtol(nptr, (char **)NULL, 10)

atol: strtol(nptr, (char **)NULL, 10)

atoll: strtoll(nptr, (char **)NULL, 10)

strtol is preferred, as atoi invokes undefined behavior upon error. See 7.22.1 "If the value of the result cannot be represented, the behavior is undefined."

Sign up to request clarification or add additional context in comments.

3 Comments

(Yes I know this question is terribly old but the accepted answer is incorrect, had to be clarified)
"If the value of the result cannot be represented, the behavior is undefined". Surely this make the function completely unusable, and is sufficient reason to consider the function effectively deprecated.
@WilliamPursell Indeed. Give the C standard committee a couple of decades more and they might realize. For example, it took them 22 years to remove gets. The very epitome of efficiency and initiative. Compare this with the MISRA-C safe subset standard, which banned all use of the ato* functions as early as 1998.
8

It does say on Apple's Mac OS X Manual Page for atoi(3) (and in the BSD man pages too) that atoi has been deprecated.

The atoi() function has been deprecated by strtol() and should not be used in new code.

I would use the strtol() equivalent just for that reason, but i doubt you have to worry about atoi() being removed.

from http://www.codecogs.com/library/computing/c/stdlib.h/atoi.php Implementation Notes

* The atoi function is not thread-safe and also not async-cancel safe. * The atoi function has been deprecated by strtol and should not be used in new code. 

6 Comments

Doesn't it depend only on the internal implementation of the atoi whether it's thread-safe or not? If not, then what makes it not thread-safe on the outside?
They must've tried really hard to make it not thread safe. The naive implementation sure is.
It is important to note that not every compiler supports sto* functions yet, like Android NDK. See this question for more: stackoverflow.com/questions/15499070/…
glibc man page for atoi says: "The atoi(), atol(), and atoll() functions are thread-safe with exceptions. These functions can be safely used in multithreaded applications, as long as setlocale(3) is not called to change the locale during their execution."
This answer, or rather the source, is incorrect/irrelevant. Whether or not a certain function is thread-safe indeed depends on the compiler implementation. I don't see why it wouldn't be. atoi is no different from strol functions in this regard. More so, atoi is most certainly not deprecated. It wasn't in 2009 and it isn't now either, in the C11 standard.
|
4

The description of atoi() has one very important point in relation to the similarities/differences to strtol()

> ... The call atoi(str) shall be equivalent to:
> (int) strtol(str, (char **)NULL, 10)
> except that the handling of errors may differ.

Try this for fun:

const char *buf = "forty two"; int t1 = atoi(buf); /* detect errors? */ int t2 = strtol(buf, NULL, 10); /* detect errors? */ 

3 Comments

I've tried your code on my compiler (GCC) and both gave me 0, so I don't see any difference :|
Hmmm, my bad! Thanks @SasQ. I thought strtol had to set errno on error, but in the specific case of my test code above, it doesn't.
@pmg Your test code doesn't seem to check errno at all.
3

No, you shouldn't use the above instead of atoi.

You should actually check the error information that strtol makes available:

i = atoi(s); 

should be replaced by

char* stopped; i = (int)strtol(s, &stopped, 10); if (*stopped) { /* handle error */ } 

Comments

0
  • atoi() is not deprecated by the prior or the current C standard.

  • atoi(nptr) is like (int)strtol(nptr, (char **)NULL, 10); except on errors.


Now, how to detect and resolve errors?

Consider using a helper function: int atoi_alt(const char *nptr, int *errorptr);

Possible errors and candidate resolutions:

  • Out-of-range: conversion leads to a value outside the [INT_MIN ... INT_MAX] range like atoi_alt("1234567890123456789012345678901234567890", ...);. Return either INT_MIN or INT_MAX (matching the sign of the original conversion) and a non-zero error.

  • No conversion: conversion fails as the string begins with non-numeric, non-white-space text like atoi_alt("!@#$1234", ...);. Return 0 and a non-zero error.

  • No conversion: conversion fails as the string is empty like atoi_alt("", ...);. Return 0 and a non-zero error.

  • Non-numeric trailing text: Initial conversion works, yet extra, non-white-space, text exists like atoi_alt("1234!@#$", ...);. Return converted value and a non-zero error. Note that with strtol(), this is not an error.

  • White-space trailing text: Initial conversion works, white-space follows like atoi_alt("1234\n", ...);. Return converted value and a zero error. Note that with strtol(), this is not an error.

  • White-space begins text: Ignore leading white-space and convert as above. Note that this is consistent with atoi() and strtol() and itself is not an error.

  • String not supplied: As nptr == NULL, return 0 and a non-zero error. Note that with strtol(), this is undefined behavior (UB).

  • Error address not supplied: Perform as above, but do not set an error.

Sample alternative code:

#include <ctype.h> #include <errno.h> #include <limits.h> #include <stdlib.h> // To Do: refine error codes, perhaps as enum? #define ATOI_BAD_ARG 1 #define ATOI_NO_CONVERSION 2 #define ATOI_RANGE 3 #define ATOI_EXTRA 4 int atoi_alt(const char *nptr, int *errorptr); // Side effect: errno is assigned. int atoi_alt(const char *nptr, int *errorptr) { int dummy; if (errorptr == NULL) { errorptr = &dummy; } if (nptr == NULL) { *errorptr = ATOI_BAD_ARG; return 0; } errno = 0; char *end; long lvalue = strtol(nptr, &end, 10); if (nptr == end) { *errorptr = ATOI_NO_CONVERSION; return 0; } #if LONG_MIN == INT_MIN && LONG_MAX == INT_MAX if (errno == ERANGE) { *errorptr = ATOI_RANGE; return (int) lvalue; } #else if (errno == ERANGE || lvalue < INT_MIN || lvalue > INT_MAX) { errno = ERANGE; *errorptr = ATOI_RANGE; return (lvalue < 0) ? INT_MIN : INT_MAX; } #endif while (isspace(((unsigned char* ) end)[0])) { end++; } *errorptr = *end ? ATOI_EXTRA : 0; return (int) lvalue; } 

Code purposely does not carry the error information back to the caller via errno - my design choice. Easy enough to amend code to do otherwise.

Comments

-3

it means that at one point in time atoi will not be available anymore. So start changing your code now

2 Comments

I get that part, but was wondering if atoi's implementation just called the code above.
This is incorrect, citation needed. Nothing in the current C standard indicates that atoi is deprecated. And this is 6 years after this answer was made, with C11 being the active standard.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.