Text arrives from users, files, and the command line as characters. "42" is three bytes - '4', '2', '\0' - and nothing in it is the number 42 until you convert it. C offers two generations of conversion functions: the short, old ones that cannot report errors, and the longer ones that can. This page shows both and explains why real programs use the second set.
The Old Family: atoi, atol, atof
They read like their names: ASCII to int, to long, to double. One argument, one result.
Leading whitespace is skipped, an optional sign is read, digits are consumed, and everything after is ignored. That is convenient until the input is wrong:
All three print 0. There is no return code, no flag, no way to ask "did that work?" - and a value that overflows int is undefined behavior rather than a reported error. For a hard-coded literal in a toy program that is tolerable. For anything a person or a file can supply, it is a silent bug generator.
The Right Tool: strtol
strtol (string to long) is the same conversion with two channels for reporting what happened.
long strtol(const char *text, char **endptr, int base);
endptr is set to the first character the function did not consume. base is the number base - use 10, or 0 to let the literal's own prefix decide (0x for hex, leading 0 for octal).
Reading endptr answers the questions atoi cannot:
end == inputmeans nothing was converted - the text did not start with a number.*end != '\0'means there was trailing content. Whether that is an error is your call: it is fine when parsing"42 apples", and a problem when the whole line should have been a number.
Overflow is reported separately through errno. The full, correct idiom is worth writing once and reusing:
Three details make this correct. errno = 0 before the call matters because the library only ever sets errno; it never clears it, so a stale value from an earlier call would be read as this call's failure. strtol returns long, which may be wider than int, so the range check against INT_MIN/INT_MAX is separate from ERANGE. And returning success as a status while delivering the value through a pointer is how C functions report "either a value or a failure" - the return value cannot do both jobs.
strtoul is the unsigned counterpart, and strtoll/strtoull handle long long.
Other Bases
Base 16 reads hexadecimal; base 0 inspects the prefix and decides for itself.
Base 0 is a trap in one specific case: a zero-padded decimal like "012" is read as octal and comes out as 10. If your input is decimal, say 10 explicitly.
Floating Point: strtod
strtod is the same shape for double, and atof has the same flaw as atoi.
strtod also accepts scientific notation ("1.5e3"), hex floats, and the words "inf" and "nan". Locale affects the decimal separator, which surprises people parsing files written elsewhere - in the default "C" locale the separator is always a dot.
Numbers to Text: snprintf
Going the other way, snprintf is the standard answer. It writes at most the size you give it, always terminates, and returns the length the full result would have needed.
The return value is the truncation check. If it is greater than or equal to the buffer size, the text did not fit:
Two things not to reach for: itoa is not part of standard C, so code using it will not compile everywhere; and sprintf is snprintf without the size limit, which means it will write past the end of your buffer without complaint.
Single Characters and '0'
The digit characters '0' through '9' are guaranteed to be consecutive, so plain subtraction converts between a digit character and its value.
Only digits behave this way - letters are not required to be consecutive, so c - 'a' is not portable for alphabet arithmetic. Guard the subtraction with isdigit before trusting it:
The cast to unsigned char is required for the same reason as in strings: the <ctype.h> functions are undefined for negative arguments, and plain char can be signed.
Which Function to Use
- Text from a user, a file, or
argv→strtol/strtodwith the full check. - A literal you wrote yourself and control →
atoiis acceptable, if unremarkable. - Number into a buffer →
snprintf, and check the return value. - One digit character → subtract
'0', afterisdigit. - Never →
gets,sprintf,itoa.
Frequently Asked Questions
How do you convert a string to an int in C?
strtol(text, &end, 10) is the correct answer: it returns the value, sets end to the first character it did not consume, and reports overflow through errno. atoi(text) is shorter but returns 0 for both "0" and "hello" with no way to tell the two apart.
What is wrong with atoi in C?
It cannot report failure. atoi("abc") returns 0, which is indistinguishable from a real zero, and overflow is undefined behavior rather than a reported error. Use strtol any time the text came from a user, a file, or a command line argument.
How do I convert an int to a string in C?
snprintf(buf, sizeof buf, "%d", n). It is standard, bounded by the buffer size, and returns the number of characters the full result needed - so a return value at or above sizeof buf tells you the text was truncated. itoa is not standard C.
How do I turn the character '7' into the number 7 in C?
Subtract '0': int digit = c - '0';. The digit characters are consecutive in every C character set, so the subtraction gives 0 through 9. Guard it with isdigit((unsigned char)c) first, since the arithmetic is meaningless for anything else.