365

How do you convert an int (integer) to a string?

I'm trying to make a function that converts the data of a struct into a string to save it in a file.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1063999
  • 3,689
  • 3
  • 14
  • 5
  • 4
    `printf` or one of its cousins should do the trick – pmg Nov 24 '11 at 13:21
  • 1
    possible duplicate of [Where is the itoa function in Linux?](http://stackoverflow.com/questions/190229/where-is-the-itoa-function-in-linux) – Paul R Nov 24 '11 at 13:27
  • 1
    you may also want to see [this FAQ](http://www.parashift.com/c++-faq-lite/serialization.html) on serialization, and maybe the following questions that relate to serialization in C: [(a)](http://stackoverflow.com/questions/144435/whats-the-best-way-to-serialize-data-in-a-language-independent-binary-format), [(b)](http://stackoverflow.com/questions/7488112/a-minimalistic-human-readable-serialisation-format-parser-for-an-embedded-system), [(c)](http://stackoverflow.com/questions/371371/serialize-data-structures-in-c) to achieve your actual intent. – moooeeeep Nov 24 '11 at 13:35
  • 4
    My usual pet semantic peeve here. You don't want to convert anything; you want to obtain a string containing a (base 10?) representation of the value of the `int`. Yeah, I know. It's a very common short cut, but it still bugs me. – dmckee --- ex-moderator kitten May 24 '14 at 02:41
  • possible duplicate of [Converting int to string in c](http://stackoverflow.com/questions/5242524/converting-int-to-string-in-c) – nawfal Jul 17 '14 at 07:18
  • 1
    Can you please unaccept the current accepted answer and accept the highest-voted one? `itoa` is non-standard, so `snprintf` is more portable. – S.S. Anne Jan 24 '20 at 22:43

11 Answers11

376

You can use sprintf to do it, or maybe snprintf if you have it:

char str[ENOUGH];
sprintf(str, "%d", 42);

Where the number of characters (plus terminating char) in the str can be calculated using:

(int)((ceil(log10(num))+1)*sizeof(char))
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 15
    To be sure tat `ENOUGH` is enough we can do it by `malloc(sizeof(char)*(int)log10(num))` – Hauleth Nov 24 '11 at 13:25
  • 4
    @Hauleth Or even +2, considering that `(int)log10(42)` is `1`. – Christian Rau Nov 24 '11 at 13:34
  • 36
    Or you can calculate it at compile-time: `#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)` – caf Nov 25 '11 at 00:31
  • 1
    @caf Note: `((CHAR_BIT * sizeof(int) - 1) / 3 + 2)` fails for unusual, but possible, `int` widths such as 18. Just eliminate the `-1`. – chux - Reinstate Monica Sep 15 '14 at 15:08
  • 5
    @hauleth Still +2 instead of +1, even with ceil: ceil(log(100)) = 2.0, not 3. So +1 for the exact-powers-of-10, and another +1 for terminating null. – not-just-yeti Feb 12 '15 at 17:23
  • 55
    You do not consider minus sign and locale: thousands separator and grouping. Please do it this way: use `int length = snprintf(NULL, 0,"%d",42);` to get length, and then alloc `length+1` chars for the string. – user2622016 Sep 28 '15 at 06:10
  • 2
    @user2622016 Calling `snprintf` with a `NULL` buffer to determine required buffer size is a great trick! [Here's a comparison of the `printf` members](http://en.cppreference.com/w/c/io/fprintf) for anyone who may be interested. – pfabri Dec 01 '16 at 16:49
  • Also, [here's a concrete example of `snprintf`](http://www.cplusplus.com/reference/cstdio/snprintf/) demonstrating how its reported buffer size may be used in other creative ways. – pfabri Dec 01 '16 at 16:56
  • 1
    How does your formula for the number of characters required work with negatives? – Nic Apr 13 '17 at 08:00
  • 1
    As @not-just-yeti said, `(int)((ceil(log10(num))+1)*sizeof(char))` is wrong. This should be correct for all possible `int` values (but I wouldn't use this abomination in real code): `(int)((floor(log10(i==INT_MIN?INT_MAX:i<0?-i:i>0?i:1)+(i>=0?2:3))))`. I dropped the `sizeof(char)` since it's always 1. Note: ISO C rules guarantee that `INT_MIN` and `INT_MAX` always have the same number of digits. – jcsahnwaldt Reinstate Monica Apr 17 '17 at 15:38
  • 1
    If the number is **zero**, then this will fail, because in C arithmetic, `log10(0) = -1`... – wvxvw Apr 09 '18 at 14:00
  • Another simple way to know exactly how many bytes you need: `sizeof(EXPAND_AND_STRINGIFY(INT_MIN))` (given `#define EXPAND_AND_STRINGIFY(macro) STRINGIFY(macro)` and `#define STRINGIFY(token) #token`). This will take the `-` sign into account (and the maximum can never take more digits than the minimum in any integer representation that conforms to the standard, so this also takes an optional `+` into account), and the terminating null byte. – mtraceur Jan 08 '23 at 05:31
163

As pointed out in a comment, itoa() is not a standard, so better use the sprintf() approach suggested in the rival answer!


You can use the itoa() function to convert your integer value to a string.

Here is an example:

int num = 321;
char snum[5];

// Convert 123 to string [buf]
itoa(num, snum, 10);

// Print our string
printf("%s\n", snum);

If you want to output your structure into a file there isn't any need to convert any value beforehand. You can just use the printf format specification to indicate how to output your values and use any of the operators from printf family to output your data.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexander Galkin
  • 12,086
  • 12
  • 63
  • 115
152

The short answer is:

snprintf( str, size, "%d", x );

The longer is: first you need to find out sufficient size. snprintf tells you length if you call it with NULL, 0 as first parameters:

snprintf( NULL, 0, "%d", x );

Allocate one character more for null-terminator.

#include <stdio.h> 
#include <stdlib.h>

int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);

If works for every format string, so you can convert float or double to string by using "%g", you can convert int to hex using "%x", and so on.

APhillips
  • 1,175
  • 9
  • 17
user2622016
  • 6,060
  • 3
  • 32
  • 53
45

After having looked at various versions of itoa for gcc, the most flexible version I have found that is capable of handling conversions to binary, decimal and hexadecimal, both positive and negative is the fourth version found at http://www.strudel.org.uk/itoa/. While sprintf/snprintf have advantages, they will not handle negative numbers for anything other than decimal conversion. Since the link above is either off-line or no longer active, I've included their 4th version below.

(Important Note: This code is GPLv3-licensed, so if you compile something with it, the result must be released under the same terms.)

/**
 * C++ version 0.4 char* style "itoa":
 * Written by Lukás Chmela
 * Released under GPLv3.
 */
char* itoa(int value, char* result, int base) {
    // check that the base if valid
    if (base < 2 || base > 36) { *result = '\0'; return result; }

    char* ptr = result, *ptr1 = result, tmp_char;
    int tmp_value;

    do {
        tmp_value = value;
        value /= base;
        *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    } while ( value );

    // Apply negative sign
    if (tmp_value < 0) *ptr++ = '-';
    *ptr-- = '\0';
  
    // Reverse the string
    while(ptr1 < ptr) {
        tmp_char = *ptr;
        *ptr--= *ptr1;
        *ptr1++ = tmp_char;
    }
    return result;
}
ogggre
  • 2,204
  • 1
  • 23
  • 19
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 8
    Also, this is considerably faster than sprintf. Could be important when dumping large files. – Eugene Ryabtsev Oct 17 '14 at 08:56
  • @Eugene Ryabtsev C does not specify the performance rating of `sprintf()` and "this is considerably faster than sprintf" may be true on your compiler but not always hold. A compiler may look into `sprintf(str, "%d", 42);` and optimize it to an optimized `itoa()` like function - certainly faster than this user. code. – chux - Reinstate Monica Sep 29 '15 at 22:44
  • 4
    @chux Yes, a compiler could optimize `sprintf(str, "%d", 42);` as appending two const chars, but that is theory. In practice people don't sprintf const ints and the itoa above is nearly as optimized as it gets. At least you could be 100% sure you would not get orders of magnitude downgrade of a generic sprintf. It would be nice to see whatever counterexample you have in mind, with compiler version and settings. – Eugene Ryabtsev Sep 30 '15 at 04:52
  • 1
    @Eugene Ryabtsev `char str[3]; sprintf(str, "%d", 42);` --> `MOV #121A,W4, MOV W4,AF4, MOV #2A,W0 = 2A, MOV #0,W4, CALL 105E` embedded compiler simple passes the buffer and 42 to a `itoa()`-like routine. – chux - Reinstate Monica Sep 30 '15 at 14:32
  • 1
    @chux If it ends in a call, it does not explain much unless we compare the called routine to the routine above (all the way down to no more calls; in assembly, if you like). If you do it as an answer with compiler version and settings, I will upvote it as useful. – Eugene Ryabtsev Oct 01 '15 at 04:25
  • 3
    It would be good to provide a way to get the output length back. I've done that here: https://stackoverflow.com/a/52111436/895245 + unit tests. – Ciro Santilli OurBigBook.com Sep 03 '18 at 08:00
  • what's `result` pointer here? since it returns char pointer also ?! – TomSawyer Jun 19 '20 at 14:32
  • @TomSawyer `result` is a pointer that is a *parameter* passed to the function which was an array (or dynamically allocated block) in the calling function of sufficient size to hold the number converted to a string. Since the largest 64-bit number has 20 digits, the array must provide at least 21 bytes of storage (including the *nul-terminating* character for end-of-string). Generally `char result[32];` in the calling function is fine. – David C. Rankin Jun 19 '20 at 15:41
  • Note that modern compilers (with optimizations turned on) will produce more efficient code on typical hardware if you just get the remainder with `%` instead of avoiding it by doing a separate multiplication. (And that such hand-optimizations are more likely to confuse and defeat optimization passes, making the hand-optimized code ultimately less efficient as optimization passes in compilers improve.) (I still +1'ed this answer though, because it's a good answer overall.) – mtraceur Oct 26 '21 at 23:38
  • @EugeneRyabtsev Of course, these debates depend upon rather we are concerned with speed or code compactness. When the later, our libraries are also a consideration. If we already need `sprintf` for something else in the program that lives in the "hot" code, then it's already sitting in the cache or `mmap`ped and residing in RAM, so just use `sprintf`. Compiler optimizations are amazing these days. But for embedded programming, `itoa` can still be important. Remember the 80/20 rule! – Daniel Santos Feb 11 '22 at 19:28
  • @DavidC.Rankin From an optimization standpoint (and presuming it matters), this gets better with constants propagation. If allowed by your compiler (i.e, same translation unit or `-flto` enabled) the compiler will "clone" `atoi`, propagate the base as a constant, and you end up with a symbol called `atoi.constprop.10` or such. If you only ever use `atoi` with the same base, the original `atoi` can be excluded from the final link. – Daniel Santos Feb 11 '22 at 19:39
  • @y.kaf. - `result` is an array of sufficient size passed in as a parameter which is filled by the function with a numerical representation of the value converted to a C-string. The address is returned as a convenience allowing immediate use, e..g `printf ("%s\n", itoa(40, result, 10));` Where the results array could be declared as `char result[64];` (or sized as desired) – David C. Rankin Aug 14 '22 at 17:02
  • @DavidC.Rankin what does `zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz` mean... – jian Oct 26 '22 at 17:17
  • @jian the string literal `zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz` is simply the complete set of characters that allows for the representation of values in `base2` to `base36`. (normally, you only deal with `base2` (binary), `base8` (octal), `base10` (decimal) and `base16` (hex), but there is no reason you can't convert to any base between `2` and `36`. – David C. Rankin Oct 26 '22 at 22:22
14

Here's another way.

#include <stdio.h>

#define atoa(x) #x

int main(int argc, char *argv[])
{
    char *string = atoa(1234567890);
    printf("%s\n", string);
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
catfood
  • 439
  • 5
  • 5
9

If you are using GCC, you can use the GNU extension asprintf function.

char* str;
asprintf(&str, "%i", 12313);
free(str);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vicente Bolea
  • 1,409
  • 16
  • 39
  • A justification [may be](https://www.gnu.org/software/libc/manual/2.37/html_node/Formatted-Output-Functions.html): *"The sprintf function can be dangerous because it can potentially output more characters than can fit in the allocation size of the string s ... To avoid this problem, you can use `snprintf` or `asprintf`"* – Peter Mortensen Feb 06 '23 at 16:43
9

Converting anything to a string should either 1) allocate the resultant string or 2) pass in a char * destination and size. Sample code below:

Both work for all int including INT_MIN. They provide a consistent output unlike snprintf() which depends on the current locale.

Method 1: Returns NULL on out-of-memory.

#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)

char *int_to_string_alloc(int x) {
  int i = x;
  char buf[INT_DECIMAL_STRING_SIZE(int)];
  char *p = &buf[sizeof buf] - 1;
  *p = '\0';
  if (i >= 0) {
    i = -i;
  }
  do {
    p--;
    *p = (char) ('0' - i % 10);
    i /= 10;
  } while (i);
  if (x < 0) {
    p--;
    *p = '-';
  }
  size_t len = (size_t) (&buf[sizeof buf] - p);
  char *s = malloc(len);
  if (s) {
    memcpy(s, p, len);
  }
  return s;
}

Method 2: It returns NULL if the buffer was too small.

static char *int_to_string_helper(char *dest, size_t n, int x) {
  if (n == 0) {
    return NULL;
  }
  if (x <= -10) {
    dest = int_to_string_helper(dest, n - 1, x / 10);
    if (dest == NULL) return NULL;
  }
  *dest = (char) ('0' - x % 10);
  return dest + 1;
}

char *int_to_string(char *dest, size_t n, int x) {
  char *p = dest;
  if (n == 0) {
    return NULL;
  }
  n--;
  if (x < 0) {
    if (n == 0) return NULL;
    n--;
    *p++ = '-';
  } else {
    x = -x;
  }
  p = int_to_string_helper(p, n, x);
  if (p == NULL) return NULL;
  *p = 0;
  return dest;
}

[Edit] as request by @Alter Mann

(CHAR_BIT*sizeof(int_type)-1)*10/33+3 is at least the maximum number of char needed to encode the some signed integer type as a string consisting of an optional negative sign, digits, and a null character..

The number of non-sign bits in a signed integer is no more than CHAR_BIT*sizeof(int_type)-1. A base-10 representation of a n-bit binary number takes up to n*log10(2) + 1 digits. 10/33 is slightly more than log10(2). +1 for the sign char and +1 for the null character. Other fractions could be used like 28/93.


Method 3: If one wants to live on the edge and buffer overflow is not a concern, a simple C99 or later solution follows which handles all int.

#include <limits.h>
#include <stdio.h>

static char *itoa_simple_helper(char *dest, int i) {
  if (i <= -10) {
    dest = itoa_simple_helper(dest, i/10);
  }
  *dest++ = '0' - i%10;
  return dest;
}

char *itoa_simple(char *dest, int i) {
  char *s = dest;
  if (i < 0) {
    *s++ = '-';
  } else {
    i = -i;
  }
  *itoa_simple_helper(s, i) = '\0';
  return dest;
}

int main() {
  char s[100];
  puts(itoa_simple(s, 0));
  puts(itoa_simple(s, 1));
  puts(itoa_simple(s, -1));
  puts(itoa_simple(s, 12345));
  puts(itoa_simple(s, INT_MAX-1));
  puts(itoa_simple(s, INT_MAX));
  puts(itoa_simple(s, INT_MIN+1));
  puts(itoa_simple(s, INT_MIN));
}

Sample output

0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3
/* Function return size of string and convert signed  *
 * integer to ascii value and store them in array of  *
 * character with NULL at the end of the array        */

int itoa(int value, char *ptr)
{
    int count = 0, temp;
    if(ptr == NULL)
        return 0;
    if(value == 0)
    {
        *ptr = '0';
        return 1;
    }

    if(value < 0)
    {
        value* = (-1);
        *ptr++ = '-';
        count++;
    }

    for(temp=value; temp>0; temp/=10, ptr++);
        *ptr = '\0';

    for(temp=value; temp>0; temp/=10)
    {
        *--ptr = temp%10 + '0';
        count++;
    }
    return count;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kannadasan
  • 47
  • 1
3

sprintf is returning the bytes and adds a null byte as well:

# include <stdio.h>
# include <string.h>

int main() {
    char buf[1024];
    int n = sprintf( buf, "%d", 2415);
    printf("%s %d\n", buf, n);
}

Output:

2415 4
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
baz
  • 1,317
  • 15
  • 10
0

Improved cnicutar answer.

Include:

#include <math.h> // log10, floor
#include <stdio.h> // sprintf
#include <stdlib.h> // abs

Create your number:

int num = 123;

Calculate length:

size_t len;
if (abs(num)) { // if not zero
    len = floor(log10(abs(num)) + 1); // taking 'round' numbers into account too
    if (num < 0) len++; // add minus sign
} else { // if zero
    len = 1;
}

Then you can store your string as a local variable:

char str[len];
sprintf(str, "%d", num);
// do stuff

or as a pointer:

char *str = malloc(len * sizeof(char));
sprintf(str, "%d", num);
// do stuff
free(str);

Hope that helps!

Emil Viesná
  • 88
  • 1
  • 12
-4

Use function itoa() to convert an integer to a string

For example:

char msg[30];
int num = 10;
itoa(num,msg,10);
Morteza Jalambadani
  • 2,190
  • 6
  • 21
  • 35
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81