2

So, I am doing my own rudimentary version of itoa(), and I just realized I don't exactly know how to modify a char* passed as parameter, or if there is something wrong with the way I am doing it...

The way I am doing it is by doing malloc() onto the buffer passed as argument, then write the number into it. This is apparently working before returning from the function (the buffer is printed correctly), but then when trying to print it back in main(), it segfaults.

If I understand the error correctly, I am changing the address buff points to inside with that malloc(), and then modify its contents, but the new malloc'd address inside is not returned. How could I do that without changing the parameters or the return value?

int itoa(int i, char *buff) {
    int length = 0;
    
    // get the length
    long temp = 1;
    while (temp <= i) {
        length++;
        temp *= 10;
    }

    buff = malloc(length + 1); // buff will have 'length' chars + one extra (\0)

    int j = 0;
    do {                            /* generate digits in reverse order */
        buff[j++] = i % 10 + '0';   /* get next digit */
    } while ((i /= 10) > 0);        /* delete it */

    buff[length] = '\0';
    
    // reverse it
    int k, l;
    char c;
    for (k = 0, l = length - 1; k<l; k++, l--) {
        c = buff[k];
        buff[k] = buff[l];
        buff[l] = c;
    }

    printf("buff's now:%s\n", buff);

    return 0;
}

int main() {
    char *buff = NULL;
    itoa(45, buff);

    printf("%s\n", buff);
}
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Lightsong
  • 312
  • 2
  • 8
  • Without changing the functions signature (arguments and types) or its return type, the only way to solve this problem is to let the caller pass in a pointer to an already allocated buffer (of sufficient length) that your function only copy into. With the restrictions you imposed, there's no other way. – Some programmer dude Dec 22 '20 at 19:50
  • Hint: `if(isdigit(buff[i])) val = buff[i] - '0';` (where val is one of the `int` types) – ryyker Dec 22 '20 at 19:51
  • Don't do the `malloc`. The definition [unofficial] says that caller must provide sufficient space in the argument to contain any possible result. See: http://www.cplusplus.com/reference/cstdlib/itoa/ The return value [if it's `char *` as in the link] must match _caller's_ passed in value. – Craig Estey Dec 22 '20 at 19:51
  • @Inian - _"pass it as a double pointer"_. question about `atoi()`, did you mean a `int *` ? – ryyker Dec 22 '20 at 19:54
  • @Someprogrammerdude and CraigEstey I see, thank you very much! Of course I had not thought about that. It also makes sense that the caller has an already allocated buffer provided to the function. – Lightsong Dec 22 '20 at 19:59
  • You are sending the pointer as the copy. So it doesn't modify the original pointer. – crackaf Dec 22 '20 at 20:41
  • Please do not edit solution announcements into the question. Create yourself an answer instead or accept one of the existing answers. – Yunnosch Dec 28 '20 at 21:50

1 Answers1

1

Your pointer isn't modified as it was copied. You can read more here. You can try this code after reading the above link.

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

int itoa_(int i, char **parabuff)
{
    int length = 0;
    // get the length
    long temp = 1;
    while (temp <= i)
    {
        length++;
        temp *= 10;
    }

    char *buff = malloc(length + 1); // buff will have 'length' chars + one extra (\0)

    int j = 0;
    do
    {                             /* generate digits in reverse order */
        buff[j++] = i % 10 + '0'; /* get next digit */
    } while ((i /= 10) > 0);      /* delete it */

    buff[length] = '\0';

    // reverse it
    int k, l;
    char c;
    for (k = 0, l = length - 1; k < l; k++, l--)
    {
        c = buff[k];
        buff[k] = buff[l];
        buff[l] = c;
    }

    printf("buff's now: %s\n", buff);

    *parabuff = buff;

    return 0;
}

int main()
{
    char *buff = NULL;
    itoa_(45, &buff);

    printf("buff in main: %s\n", buff);
}

//OUTPUT
buff's now: 45
buff in main: 45
crackaf
  • 492
  • 2
  • 11