As an exercise, I limited my self to the man pages. I didn't look for a previous existing implementation because I wanted to see how well I could do on my own. I also tried to handle as many cases as I could think of. I am sure there are weaknesses so feel free to point them out. Where can I improve my usage of the C standard library, etc.char *itoa(int i){  short digit_cnt;  short index;  void *ret;  char digit;  int tmp;  errno = 0;  feclearexcept(FE_ALL_EXCEPT);  if (i == 0) {    digit_cnt = 1;  } else {    tmp = (i == INT_MIN) ? (i + 1) : i;    digit_cnt = floor(log10(abs(tmp))) + 1;    if (errno || fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |      FE_UNDERFLOW)) {      return NULL;    }  }  if (i < 0) {    ++digit_cnt;  }  ++digit_cnt; // '\0'  errno = 0;  if ((ret = malloc(digit_cnt * sizeof(char))) == NULL || errno) {    print_error_msg(errno);    free(ret);    return NULL;  }  // This made debugging easier.  memset(ret, '0', digit_cnt * sizeof(char));  index = digit_cnt;  ((char*)ret)[--index] = '\0';  tmp = i;  do {    digit = (char)((int)'0' + abs(tmp % 10));    ((char*)ret)[--index] = digit;    tmp /= 10;  } while (tmp != 0);  if (i < 0) {    ((char*)ret)[--index] = '-';  }  return ret;}
C itoa implementation
c;programming challenge;reinventing the wheel
No reason to use floating point math here.  At a minimum, it creates a non-portability as the aspects of FP math have corner cases and precision issues that will fail itoa(int i).  At worst, it invoke undefined behavior: abs(tmp) may be UB if tmp == INT_MIN. (Code does use tmp = (i == INT_MIN) ? (i + 1) : i; to handle that case, but it call be handled cleaner in other ways.)  Rare, but potential inexact result from log10() leads to off-by-one with floor().  C does not specify that double can represent every int. Think of a 64-bit int and 64-bit double. Code like log10(abs(tmp)) is a potential for conversion inaccuracies.// Many issuesdigit_cnt = floor(log10(abs(tmp))) + 1;Code is clearing a global value in code that is very unexpected to do so.  feclearexcept(FE_ALL_EXCEPT);  I would not expect the side-effect of itoa() to clear FP exceptions.errno = 0 is another unexpected side-effect of this itoa().  Like strtol() and other conversion functions, setting errno to 0 is the caller's responsibility.  C does not specify that errno is set to some value on a out-of-memory.  Since this post is not tagged OS specific, I am on the fence as to if errno should be set to indicate that error.Excessive malloc().  Just malloc() the space needed, not the worst case size. I see OP is right-sizing, yet in a dangerous fashion.  OP's code relies on log10() coming up with the exact answer when i == power-of-10.  Weak FP math libraries have been known to come up just short of the expected value.  No only would this generate the wrong conversion, it would cause memory corruption.Avoid the name itoa() as that is well used by others.Note: C99 or later dependency.  tmp % 10 and tmp /= 10 may not return the value expected with early compliers.  I am noting it, but not think it if worth the effort to account for those compliers.  YMMVAll in all a good attempt, but starting off will FP, really overcomplicated things and created unneeded dependencies on FP math/attributes.  The FP math was only used to size the buffer, when a worst case buffer could be instead for the intermediate results.  Thinking of embedded project, that log10() inclusion is especially space and time expensive.A simple C99 alternative.  #include <stdlib.h>// Worst case size needed: about bit_width * log10(2) + a few extra#define INT_SIZE (sizeof(int)*CHAR_BIT / 3 + 3)char *MH_itoa(int i) {  char buf[INT_SIZE];  char *p = &buf[sizeof buf - 1];  *p = '\0';  int j = i;  //  Let us work with negative numbers to avoid problems with abs(INT_MIN)  if (j > 0) {    j = -j;  }  do {    p--;    *p = '0' - j % 10;    j /= 10;  } while (j);  if (i < 0) {    p--;    *p = '-';  }  // Right size the allocation  size_t size = (size_t) (&buf[sizeof buf] - p);  char *dest = malloc(size);  if (dest) {    memcpy(dest, p, size);  }  return dest;}