1

i have some code:

char * itoa(int a)
{
    char (*t)[16]=(char(*)[16])malloc(1*sizeof(char[16]));
    sprintf(*t,"%d",a);
    return *t;
}
// ...
mvwprintw(my_menu_win,i+1,2,itoa(i));

can i free memory from malloc, without add temporary variables? e.g:

temp=itoa(i);
mvwprintw(my_menu_win,i+1,2,temp);
free(temp);
askovpen
  • 2,438
  • 22
  • 37
  • 4
    To free it, you need a pointer to it, for that you need a variable to hold the pointer. Aside, why `char (*)[16]` and not plain `char*`? – Daniel Fischer Nov 05 '12 at 11:35
  • 1
    just as a side note, you shouldn't cast the result of malloc [do-i-cast-the-result-of-malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – iabdalkader Nov 05 '12 at 11:42
  • This is why `itoa` takes a `char *` as the second argument. – Aesthete Nov 05 '12 at 11:55
  • Well, sort of. It is possible to add conservative garbage collection to C, and then you don't need any explicit calls to free: http://en.wikipedia.org/wiki/Boehm_garbage_collector – Thomas Padron-McCarthy Nov 05 '12 at 12:04

4 Answers4

4

You shouldn't use malloc for buffers for which you know that the scope is restricted anyhow.

A good solution for such cases where you might want to keep a buffer for a while are compound literals as of C99. I'd go for something like

char const* itoa(int a, char (*buffer)[16]) {
    sprintf(*buffer,"%d",a);
    return *buffer;
}

#define ITOA(A) itoa((A), &(char[16]){ 0 })

The pointer to array for the function assures that a buffer of 16 elements is passed.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
3

In short: No.

To free allocated memory you need a reference to it.

If you could change your conversion API, a possible work around could be to use an externally provided buffer:

char * itoa(char * t, int i)
{
  sprintf(t,"%d",a);
  return t;
}

Call itoa() this way then:

{
  char buffer [16];

  mvwprintw(my_menu_win,i+1,2,itoa(buffer, i));
}

Alternatively (C99 only) one could do the call to itoa() this way:

mvwprintw(my_menu_win,i+1,2,itoa((char[16]){0}, i));

So to clean up this a macro helps:

#define ITOA_0(i) itoa((char[16]){0}, i) /* init array with 0s */
#define ITOA(i) itoa((char[16]){}, i) /* do not init array with 0s -> faster, but none ISO */

...

mvwprintw(my_menu_win,i+1,2,ITOA(i));
alk
  • 69,737
  • 10
  • 105
  • 255
0

another way to do it, is to alloc a static array in the function, this way you won't have to free it at all:

const char* itoa(int a)
{
    static char t[16];
    sprintf(t,"%d",a);
    return t;
}

mvwprintw(my_menu_win,i+1,2,itoa(i));

Note:

This way is not thread-safe and cannot be used more than once as an argument to a function.

iabdalkader
  • 17,009
  • 4
  • 47
  • 74
  • 4
    It's a possibility but don't forget to mention that it wouldn't work for threaded code or used multiple times in a function call. `mvwprintw(my_menu_win,i+1,2,itoa(i), itoa(j));` would not produce the desired result. – Patrick Schlüter Nov 05 '12 at 11:55
0

Several issues:

Your itoa function compiles by accident. A pointer to array of char is a different type from a pointer to char, and this would have thrown a warning but for the fact you're returning *t instead of t. Given that t has type "pointer to 16-element array of char", the expression *t has type "16-element array of char". Except when it is the operand of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and its value will be the address of the first element of the array. So you're returning the correct type by accident.

You do not need to cast the result of malloc (at least as of C89). Here's a typical template for a malloc call:

T *p = malloc(N * sizeof *p);

where N is the number of elements of type T you're allocating. So you could rewrite your call as

char *t = malloc(16 * sizeof *t);

although in this particular case the sizeof is redundant, since sizeof char == 1. Then the rest of your code would be

sprintf(t, "%d", a);
return t;

Then at some point later on you would call free on the value returned by your implementation of itoa. Although frankly Jens Gustedt's solution is better if you're using a C99 or later compiler.

John Bode
  • 119,563
  • 19
  • 122
  • 198