0

I am beginner to C language and a thing that I can't understand very well is the use of malloc. So I decide to create this example. I would like to understand why it doesn't print out the buffer data and what is the best practice to do this.

#include <stdio.h>      /* printf, scanf, NULL */
#include <stdlib.h>     /* malloc, free, rand */

void f(char * buffer, int i) {
  buffer = (char *) malloc(i+1);
  if (buffer==NULL) 
    exit (1);

  for (int n=0; n<i; n++)
    buffer[n]=rand()%26+'a';

  buffer[i]='\0';
}

int main ()
{
  char * buffer;
  f(buffer, 5);
  printf ("Random string: %s\n",buffer);
  free (buffer);

  return 0;
}

Thanks

Leandro Lima
  • 1,140
  • 3
  • 24
  • 42

5 Answers5

4

Your buffer = (char *) malloc(i+1); has no effect outside the function. In effect the function is changing its own copy of buffer, and the caller (main) never sees this change. This is all very well explained in a C FAQ.

Instead of passing it as a parameter, you could return the buffer, since the function doesn't return anything at the moment:

char *f(int i)
    /* ... */
    return buffer;

/* ... */

char * buffer = f(5); 

  • In C casting malloc is a unnecessary, and often considered a dubious practice
  • The n and i variable names are somewhat misleading: one expects them the other way around
  • f is not a goot name for a function
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • My doubt is, if I create a pointer inside a function scope, returning it, it will remain valid outside the function? I mean, at the end of the function, the pointer doesn't exist anymore... – Leandro Lima Mar 28 '13 at 15:23
  • @Leandro You're right to worry. But think of it this way: the pointer itself doesn't exist anymore, that's for sure. But just before it got destroyed, it managed to convey its contents, in effect an address. So now someone else (`buffer` from `main`) holds that address. **So it's safe**, `f` can safely kill all its local variables. – cnicutar Mar 28 '13 at 15:26
2

In order to modify pointer passed to the function, you have to use pointer to pointer:

void f(char** buffer, int i) {
  *buffer = malloc(i+1);
  if (*buffer==NULL) 
    exit (1);

  for (int n=0; n<i; n++)
    (*buffer)[n]=rand()%26+'a';

  (*buffer)[i]='\0';
}

Usage:

char* buff;

f(&buff, len);
viraptor
  • 33,322
  • 10
  • 107
  • 191
Alex
  • 9,891
  • 11
  • 53
  • 87
1

Variables are passed by value to functions.

When you call f(buffer, 5), then it does not pass the variable buffer to function f; it only copies the value of the variable buffer. In function f, a new variable named buffer (the parameter variable) is created. When you change the value of that variable, the original variable that you passed in from main is not affected.

Different ways to solve this:

Make f return the pointer, and save it in buffer in main:

char * f(int i) {
    char * buffer = malloc(i + 1);

    /* ... */

    return buffer;
}

int main() {
    char * buffer = f(5);

    /* ... */

    return 0;
}

Or pass a pointer to a pointer to f; in main, pass the address of buffer:

void f(char ** buffer, int i) {
    *buffer = malloc(i + 1);

    /* ... */
}

int main() {
    char * buffer;
    f(&buffer, 5);

    /* ... */

    return 0;
}        
Jesper
  • 202,709
  • 46
  • 318
  • 350
0

You cannot change the original value of variables that were passed-by-value.

If you want to malloc in a function, and return the result of malloc in a variable, then that variable must be passed-by-reference.

E.g. instead of:

void f(char * buffer, int i);

It should be:

void f(char **buffer, int i);
cnst
  • 25,870
  • 6
  • 90
  • 122
0

CNICUTAR is right, but here are interesting information :

MALLOC :

Don't cast malloc (here is an interesting topic about it : Do I cast the result of malloc?).

FOR LOOP :

For the for loop you should use this way (C89 version) :

int i;
for (i = 0; ...)

Regards,

Community
  • 1
  • 1
Joze
  • 1,285
  • 4
  • 19
  • 33