itoa()
is a really handy function to convert a number to a string. Linux does not seem to have itoa()
, is there an equivalent function or do I have to use sprintf(str, "%d", num)
?

- 2,759
- 1
- 28
- 40

- 33,531
- 22
- 69
- 89
-
4any reason not to use `sprintf(str, "%d", num)`? is it much slower than `itoa`? – Oleg Vazhnev Sep 15 '14 at 18:53
-
5@javapowered, for one, `itoa` allows arbitrary base conversion, `printf` specifiers don't. – vladr Aug 26 '16 at 15:35
-
@javapowered sprintf() is not signal safe – lunesco Apr 03 '19 at 15:28
-
Any reason not to use `gcvt()` from standard library? – C-- May 06 '19 at 10:13
-
@C--, for one, `gcvt` is not part of C standard and POSIX.1-2008 removed it from POSIX too. – rootkea Apr 06 '22 at 05:39
18 Answers
EDIT: Sorry, I should have remembered that this machine is decidedly non-standard, having plugged in various non-standard libc
implementations for academic purposes ;-)
As itoa()
is indeed non-standard, as mentioned by several helpful commenters, it is best to use sprintf(target_string,"%d",source_int)
or (better yet, because it's safe from buffer overflows) snprintf(target_string, size_of_target_string_in_bytes, "%d", source_int)
. I know it's not quite as concise or cool as itoa()
, but at least you can Write Once, Run Everywhere (tm) ;-)
Here's the old (edited) answer
You are correct in stating that the default gcc libc
does not include itoa()
, like several other platforms, due to it not technically being a part of the standard. See here for a little more info. Note that you have to
#include <stdlib.h>
Of course you already know this, because you wanted to use itoa()
on Linux after presumably using it on another platform, but... the code (stolen from the link above) would look like:
Example
/* itoa example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
char buffer [33];
printf ("Enter a number: ");
scanf ("%d",&i);
itoa (i,buffer,10);
printf ("decimal: %s\n",buffer);
itoa (i,buffer,16);
printf ("hexadecimal: %s\n",buffer);
itoa (i,buffer,2);
printf ("binary: %s\n",buffer);
return 0;
}
Output:
Enter a number: 1750 decimal: 1750 hexadecimal: 6d6 binary: 11011010110

- 2,898
- 2
- 22
- 29

- 43,589
- 7
- 49
- 57
-
1Hmmm, compiling that on Debian gives me "undefined reference to `itoa'". Maybe something is wrong with my system. – Adam Pierce Oct 10 '08 at 05:38
-
I get the same on Ubuntu 8.04. I can find no reference to itoa in stdio.h or stdlib.h either (not suprising since it is not part of the standard) – camh Oct 10 '08 at 05:39
-
edited for correctness, thanks guys! sorry, I always forget that this isn't a vanilla Linux box ;-) – Matt J Oct 10 '08 at 05:53
-
I have edited the answer to include the buffer size argument; I believe everything is as it should be now, I don't see a problem with the order of the arguments per se. Am I missing something? – Matt J Jan 07 '10 at 23:38
-
It doesn't work for Linux? what is the outcome of the question/answer (Non standard seems to be all linuxes?) – May 15 '13 at 08:27
-
should this compile in Ubuntu using gcc? (doens't compile on my machine) – Oleg Vazhnev Sep 15 '14 at 18:55
-
How could buffer overflow ever occur? I certainly know that given a 32 bit number, the string can never exceed 34 "TCHAR" (assuming negative binary number) – user877329 Apr 06 '15 at 14:13
-
-
`sprintf()` doesn't work. How to replace `itoa(n,buffer,13);`? – 12431234123412341234123 Aug 10 '23 at 10:52
itoa
is not a standard C function. You can implement your own. It appeared in the first edition of Kernighan and Ritchie's The C Programming Language, on page 60. The second edition of The C Programming Language ("K&R2") contains the following implementation of itoa
, on page 64. The book notes several issues with this implementation, including the fact that it does not correctly handle the most negative number
/* itoa: convert n to characters in s */
void itoa(int n, char s[])
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do { /* generate digits in reverse order */
s[i++] = n % 10 + '0'; /* get next digit */
} while ((n /= 10) > 0); /* delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
The function reverse
used above is implemented two pages earlier:
#include <string.h>
/* reverse: reverse string s in place */
void reverse(char s[])
{
int i, j;
char c;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

- 254,901
- 44
- 429
- 631

- 104,019
- 25
- 176
- 264
-
well, maybe let's avoid calling strlen() within the loop - it should be called once, before the loop starts... second thing: do we need two counters (i and j) ? wouldn't it be enough to iterate i from 0 to < mid (len/2) and swap elements under indices i and len - 1 - i ? – moremover Jan 05 '23 at 09:51
-
@moremover; This implementation is from "The C Programming Language" by K&R, not mine. – haccks Jan 05 '23 at 13:46
-
yeah... strlen() is called before the loop actually... didn't notice it at first... – moremover Jan 10 '23 at 14:02
-
-
Handling the most-negative number is easily solved by taking the unsigned absolute value. `unsigned abs = n < 0 ? (0U - n) : n`. Also, instead of reversing as a 2nd step, you can store backwards starting from the end of the buffer, or into a small scratch buffer, so you only need `memmove` or `memcpy`. (The upper limit on buffer size is about log10(INT_MAX), e.g. the longest signed 64-bit number is 19 decimal digits plus a `'-'`. But I don't know a good way to make a compile-time constant expression out of INT_MAX or INT_MIN, and a hard-coded `char buf[24]` is ugly.) – Peter Cordes Mar 04 '23 at 01:45
If you are calling it a lot, the advice of "just use snprintf" can be annoying. So here's what you probably want:
const char *my_itoa_buf(char *buf, size_t len, int num)
{
static char loc_buf[sizeof(int) * CHAR_BITS]; /* not thread safe */
if (!buf)
{
buf = loc_buf;
len = sizeof(loc_buf);
}
if (snprintf(buf, len, "%d", num) == -1)
return ""; /* or whatever */
return buf;
}
const char *my_itoa(int num)
{ return my_itoa_buf(NULL, 0, num); }

- 2,825
- 18
- 16
-
19It's not just non-thread safe, it's not very safe at all :- void some_func(char* a, char* b); some_func(itoa(123), itoa(456)); Care to guess what the function recieves? – jcoder Nov 13 '12 at 12:55
-
Also, `const` qualifiers do nothing on function return types -- you would know this if you turned on compiler warnings :) – cat Sep 22 '16 at 17:25
-
9@cat But there aren’t any const-qualified return types here. `const char *` is a non-const pointer to const, which makes a lot of sense and is correct. – Chortos-2 Oct 14 '16 at 00:16
-
1@Chortos-2 That's interesting, you are, of course, completely correct -- I didn't realise the semantic difference in meaning of `const` between `const int f (void) { ...` and `const int* f (void) { ...`, but now having tried it with a compiler, it makes sense. – cat Oct 14 '16 at 00:22
-
The sizing of the static buffer makes no sense at all, since the string put into it is not binary. On a typical machine it's going to be 32 characters, but (assuming 32-bit `int`) the longest string is `"-2147483648"` which needs only 12 characters. Maybe it's a safe, generous, upper bound, though? – unwind Feb 01 '19 at 12:28
-
Edit: I just found out about std::to_string
which is identical in operation to my own function below. It was introduced in C++11 and is available in recent versions of gcc, at least as early as 4.5 if you enable the c++0x extensions.
Not only is
itoa
missing from gcc, it's not the handiest function to use since you need to feed it a buffer. I needed something that could be used in an expression so I came up with this:
std::string itos(int n)
{
const int max_size = std::numeric_limits<int>::digits10 + 1 /*sign*/ + 1 /*0-terminator*/;
char buffer[max_size] = {0};
sprintf(buffer, "%d", n);
return std::string(buffer);
}
Ordinarily it would be safer to use snprintf
instead of sprintf
but the buffer is carefully sized to be immune to overrun.
See an example: http://ideone.com/mKmZVE

- 299,747
- 42
- 398
- 622
As Matt J wrote, there is itoa
, but it's not standard. Your code will be more portable if you use snprintf
.

- 7,499
- 2
- 27
- 62
Following function allocates just enough memory to keep string representation of the given number and then writes the string representation into this area using standard sprintf
method.
char *itoa(long n)
{
int len = n==0 ? 1 : floor(log10l(labs(n)))+1;
if (n<0) len++; // room for negative sign '-'
char *buf = calloc(sizeof(char), len+1); // +1 for null
snprintf(buf, len+1, "%ld", n);
return buf;
}
Don't forget to free
up allocated memory when out of need:
char *num_str = itoa(123456789L);
// ...
free(num_str);
N.B. As snprintf copies n-1 bytes, we have to call snprintf(buf, len+1, "%ld", n) (not just snprintf(buf, len, "%ld", n))

- 9,060
- 5
- 45
- 53
-
4It's not a good idea to call your function `itoa` but give it different behaviour to what common implementations of `itoa` actually have. This function is an OK idea but call it something else :) I'd also suggest using `snprintf` to calculate the buffer length instead of the floating point string; floating point can have corner case inaccuracies. And [don't cast calloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – M.M Sep 24 '14 at 12:44
-
This should use `labs` if it's going to take a long integer. Else it might truncate. – Schwern Dec 18 '15 at 11:11
-
`snprintf` into a fixed-size tmp buffer like `char buf[64]` to get the length, then `malloc` and copy into that. You're not getting any benefit out of `calloc` over `malloc`, since you write all the bytes. Extra copying of a very short string is less bad than having to call floating point log10. A fast approximation with an integer log2 could be useful, though, if you have a bit-scan function that will reliably inline to something efficient (like `bsr` on x86). (Alternative: `malloc` a 64 byte buffer and then `realloc` after you know the final length.) – Peter Cordes Aug 10 '17 at 08:23
Reading the code of guys who do it for a living will get you a LONG WAY.
Check out how guys from MySQL did it. The source is VERY WELL COMMENTED and will teach you much more than hacked up solutions found all over the place.
MySQL's implementation of int2str
I provide the mentioned implementation here; the link is here for reference and should be used to read the full implementation.
char *
int2str(long int val, char *dst, int radix,
int upcase)
{
char buffer[65];
char *p;
long int new_val;
char *dig_vec= upcase ? _dig_vec_upper : _dig_vec_lower;
ulong uval= (ulong) val;
if (radix < 0)
{
if (radix < -36 || radix > -2)
return NullS;
if (val < 0)
{
*dst++ = '-';
/* Avoid integer overflow in (-val) for LLONG_MIN (BUG#31799). */
uval = (ulong)0 - uval;
}
radix = -radix;
}
else if (radix > 36 || radix < 2)
return NullS;
/*
The slightly contorted code which follows is due to the fact that
few machines directly support unsigned long / and %. Certainly
the VAX C compiler generates a subroutine call. In the interests
of efficiency (hollow laugh) I let this happen for the first digit
only; after that "val" will be in range so that signed integer
division will do. Sorry 'bout that. CHECK THE CODE PRODUCED BY
YOUR C COMPILER. The first % and / should be unsigned, the second
% and / signed, but C compilers tend to be extraordinarily
sensitive to minor details of style. This works on a VAX, that's
all I claim for it.
*/
p = &buffer[sizeof(buffer)-1];
*p = '\0';
new_val= uval / (ulong) radix;
*--p = dig_vec[(uchar) (uval- (ulong) new_val*(ulong) radix)];
val = new_val;
while (val != 0)
{
ldiv_t res;
res=ldiv(val,radix);
*--p = dig_vec[res.rem];
val= res.quot;
}
while ((*dst++ = *p++) != 0) ;
return dst-1;
}

- 1,048,767
- 296
- 4,058
- 3,343

- 405
- 3
- 10
-
2A link to a potential solution is always welcome, but please [add context around the link](http://meta.stackoverflow.com/a/8259/169503) so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. Take into account that being _barely more than a link to an external site_ is a possible reason as to [Why and how are some answers deleted?](http://stackoverflow.com/help/deleted-answers). – Tunaki Apr 03 '16 at 21:29
-
4So what's so good about the snippet you posted here? What should future readers look out for? – Martijn Pieters Apr 04 '16 at 12:03
Where is the itoa function in Linux?
There is no such function in Linux. I use this code instead.
/*
=============
itoa
Convert integer to string
PARAMS:
- value A 64-bit number to convert
- str Destination buffer; should be 66 characters long for radix2, 24 - radix8, 22 - radix10, 18 - radix16.
- radix Radix must be in range -36 .. 36. Negative values used for signed numbers.
=============
*/
char* itoa (unsigned long long value, char str[], int radix)
{
char buf [66];
char* dest = buf + sizeof(buf);
boolean sign = false;
if (value == 0) {
memcpy (str, "0", 2);
return str;
}
if (radix < 0) {
radix = -radix;
if ( (long long) value < 0) {
value = -value;
sign = true;
}
}
*--dest = '\0';
switch (radix)
{
case 16:
while (value) {
* --dest = '0' + (value & 0xF);
if (*dest > '9') *dest += 'A' - '9' - 1;
value >>= 4;
}
break;
case 10:
while (value) {
*--dest = '0' + (value % 10);
value /= 10;
}
break;
case 8:
while (value) {
*--dest = '0' + (value & 7);
value >>= 3;
}
break;
case 2:
while (value) {
*--dest = '0' + (value & 1);
value >>= 1;
}
break;
default: // The slow version, but universal
while (value) {
*--dest = '0' + (value % radix);
if (*dest > '9') *dest += 'A' - '9' - 1;
value /= radix;
}
break;
}
if (sign) *--dest = '-';
memcpy (str, dest, buf +sizeof(buf) - dest);
return str;
}

- 203
- 3
- 5
-
You should edit your answer to explain how this code answers the question. – C. Helling Oct 13 '17 at 14:45
-
-
calandoa, can you give precise values (value,radix) that do not work ? – rick-rick-rick Dec 11 '20 at 08:23
-
@rick-rick-rick (don't forget the @ so the user is notified!): postive radix and negative value. BTW do not use negative radix, or do it properly: https://en.wikipedia.org/wiki/Negative_base – calandoa Dec 15 '20 at 20:14
i tried my own implementation of itoa(), it seem's work in binary, octal, decimal and hex
#define INT_LEN (10)
#define HEX_LEN (8)
#define BIN_LEN (32)
#define OCT_LEN (11)
static char * my_itoa ( int value, char * str, int base )
{
int i,n =2,tmp;
char buf[BIN_LEN+1];
switch(base)
{
case 16:
for(i = 0;i<HEX_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%x" ,value);
break;
case 10:
for(i = 0;i<INT_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%d" ,value);
break;
case 8:
for(i = 0;i<OCT_LEN;++i)
{
if(value/base>0)
{
n++;
}
}
snprintf(str, n, "%o" ,value);
break;
case 2:
for(i = 0,tmp = value;i<BIN_LEN;++i)
{
if(tmp/base>0)
{
n++;
}
tmp/=base;
}
for(i = 1 ,tmp = value; i<n;++i)
{
if(tmp%2 != 0)
{
buf[n-i-1] ='1';
}
else
{
buf[n-i-1] ='0';
}
tmp/=base;
}
buf[n-1] = '\0';
strcpy(str,buf);
break;
default:
return NULL;
}
return str;
}

- 31
- 2
direct copy to buffer : 64 bit integer itoa hex :
char* itoah(long num, char* s, int len)
{
long n, m = 16;
int i = 16+2;
int shift = 'a'- ('9'+1);
if(!s || len < 1)
return 0;
n = num < 0 ? -1 : 1;
n = n * num;
len = len > i ? i : len;
i = len < i ? len : i;
s[i-1] = 0;
i--;
if(!num)
{
if(len < 2)
return &s[i];
s[i-1]='0';
return &s[i-1];
}
while(i && n)
{
s[i-1] = n % m + '0';
if (s[i-1] > '9')
s[i-1] += shift ;
n = n/m;
i--;
}
if(num < 0)
{
if(i)
{
s[i-1] = '-';
i--;
}
}
return &s[i];
}
note: change long to long long for 32 bit machine. long to int in case for 32 bit integer. m is the radix. When decreasing radix, increase number of characters (variable i). When increasing radix, decrease number of characters (better). In case of unsigned data type, i just becomes 16 + 1.

- 49
- 3
- 9
Here is a much improved version of Archana's solution. It works for any radix 1-16, and numbers <= 0, and it shouldn't clobber memory.
static char _numberSystem[] = "0123456789ABCDEF";
static char _twosComp[] = "FEDCBA9876543210";
static void safestrrev(char *buffer, const int bufferSize, const int strlen)
{
int len = strlen;
if (len > bufferSize)
{
len = bufferSize;
}
for (int index = 0; index < (len / 2); index++)
{
char ch = buffer[index];
buffer[index] = buffer[len - index - 1];
buffer[len - index - 1] = ch;
}
}
static int negateBuffer(char *buffer, const int bufferSize, const int strlen, const int radix)
{
int len = strlen;
if (len > bufferSize)
{
len = bufferSize;
}
if (radix == 10)
{
if (len < (bufferSize - 1))
{
buffer[len++] = '-';
buffer[len] = '\0';
}
}
else
{
int twosCompIndex = 0;
for (int index = 0; index < len; index++)
{
if ((buffer[index] >= '0') && (buffer[index] <= '9'))
{
twosCompIndex = buffer[index] - '0';
}
else if ((buffer[index] >= 'A') && (buffer[index] <= 'F'))
{
twosCompIndex = buffer[index] - 'A' + 10;
}
else if ((buffer[index] >= 'a') && (buffer[index] <= 'f'))
{
twosCompIndex = buffer[index] - 'a' + 10;
}
twosCompIndex += (16 - radix);
buffer[index] = _twosComp[twosCompIndex];
}
if (len < (bufferSize - 1))
{
buffer[len++] = _numberSystem[radix - 1];
buffer[len] = 0;
}
}
return len;
}
static int twosNegation(const int x, const int radix)
{
int n = x;
if (x < 0)
{
if (radix == 10)
{
n = -x;
}
else
{
n = ~x;
}
}
return n;
}
static char *safeitoa(const int x, char *buffer, const int bufferSize, const int radix)
{
int strlen = 0;
int n = twosNegation(x, radix);
int nuberSystemIndex = 0;
if (radix <= 16)
{
do
{
if (strlen < (bufferSize - 1))
{
nuberSystemIndex = (n % radix);
buffer[strlen++] = _numberSystem[nuberSystemIndex];
buffer[strlen] = '\0';
n = n / radix;
}
else
{
break;
}
} while (n != 0);
if (x < 0)
{
strlen = negateBuffer(buffer, bufferSize, strlen, radix);
}
safestrrev(buffer, bufferSize, strlen);
return buffer;
}
return NULL;
}

- 2,631
- 1
- 23
- 25
Where is the itoa function in Linux?
As itoa()
is not standard in C, various versions with various function signatures exists.
char *itoa(int value, char *str, int base);
is common in *nix.
Should it be missing from Linux or if code does not want to limit portability, code could make it own.
Below is a version that does not have trouble with INT_MIN
and handles problem buffers: NULL
or an insufficient buffer returns NULL
.
#include <stdlib.h>
#include <limits.h>
#include <string.h>
// Buffer sized for a decimal string of a `signed int`, 28/93 > log10(2)
#define SIGNED_PRINT_SIZE(object) ((sizeof(object) * CHAR_BIT - 1)* 28 / 93 + 3)
char *itoa_x(int number, char *dest, size_t dest_size) {
if (dest == NULL) {
return NULL;
}
char buf[SIGNED_PRINT_SIZE(number)];
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value
int neg_num = number < 0 ? number : -number;
// Form string
*p = '\0';
do {
*--p = (char) ('0' - neg_num % 10);
neg_num /= 10;
} while (neg_num);
if (number < 0) {
*--p = '-';
}
// Copy string
size_t src_size = (size_t) (&buf[sizeof buf] - p);
if (src_size > dest_size) {
// Not enough room
return NULL;
}
return memcpy(dest, p, src_size);
}
Below is a C99 or later version that handles any base [2...36]
char *itoa_x(int number, char *dest, size_t dest_size, int base) {
if (dest == NULL || base < 2 || base > 36) {
return NULL;
}
char buf[sizeof number * CHAR_BIT + 2]; // worst case: itoa(INT_MIN,,,2)
char *p = &buf[sizeof buf - 1];
// Work with negative absolute value to avoid UB of `abs(INT_MIN)`
int neg_num = number < 0 ? number : -number;
// Form string
*p = '\0';
do {
*--p = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(neg_num % base)];
neg_num /= base;
} while (neg_num);
if (number < 0) {
*--p = '-';
}
// Copy string
size_t src_size = (size_t) (&buf[sizeof buf] - p);
if (src_size > dest_size) {
// Not enough room
return NULL;
}
return memcpy(dest, p, src_size);
}
For a C89 and onward compliant code, replace inner loop with
div_t qr;
do {
qr = div(neg_num, base);
*--p = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-qr.rem];
neg_num = qr.quot;
} while (neg_num);

- 143,097
- 13
- 135
- 256
glibc internal implementation
glibc 2.28 has an internal implementation:
which is used in several places internally, but I could not find if it can be exposed or how.
At least that should be a robust implementation if you are willing to extract it.
This question asks how to roll your own: How to convert an int to string in C?

- 347,512
- 102
- 1,199
- 985
If you just want to print them:
void binary(unsigned int n)
{
for(int shift=sizeof(int)*8-1;shift>=0;shift--)
{
if (n >> shift & 1)
printf("1");
else
printf("0");
}
printf("\n");
}

- 69
- 3
The replacement with snprintf is NOT complete!
It covers only bases: 2, 8, 10, 16, whereas itoa works for bases between 2 and 36.
Since I was searching a replacement for base 32, I guess I'll have to code my own!

- 29
- 5
I would prefer this: https://github.com/wsq003/itoa_for_linux
It should be the fastest itoa() ever. We use itoa() instead of sprintf() for performance reason, so a fastest itoa() with limited feature is reasonable and worthwhile.

- 507
- 1
- 4
- 10
You can use this program instead of sprintf.
void itochar(int x, char *buffer, int radix);
int main()
{
char buffer[10];
itochar(725, buffer, 10);
printf ("\n %s \n", buffer);
return 0;
}
void itochar(int x, char *buffer, int radix)
{
int i = 0 , n,s;
n = s;
while (n > 0)
{
s = n%radix;
n = n/radix;
buffer[i++] = '0' + s;
}
buffer[i] = '\0';
strrev(buffer);
}

- 30,042
- 15
- 70
- 103
-
4There are so many bugs in this code: 1) Doesn't actually convert hex correctly. 2) Doesn't convert 0 at all. 3) Doesn't work with negative numbers. 4) No checking for buffer overrun. I will post an improved version of this code shortly. – Chris Desjardins Apr 16 '13 at 14:43