tags:

views:

371

answers:

6

Hi,

I'm a bit new to C's malloc function, but from what I know it should store the value in the heap, so you can reference it with a pointer from outside the original scope. I created a test program that is supposed to do this but I keep getting the value 0, after running the program. What am I doing wrong?

int f1(int * b) {
 b = malloc(sizeof(int));
 *b = 5;
}

int main() {
 int * a;
 f1(a);
 printf("%d\n", a);
 return 0;
}

+4  A: 

The memory itself persists, but it leaks because you're not providing the allocated pointer to the caller. Also, you're printing a when you should be printing *a. Finally, you're not returning an int from f1.

Try:

void f1(int **b) {
 *b = malloc(sizeof(int));
 **b = 5;
}

int main() {
 int *a;
 f1(&a);
 printf("%d\n", *a);
 free(a);
 return 0;
}
Matthew Flaschen
A: 

Your problem is actually not related to malloc, but rather the fact that you're passing the value the pointer currently holds, rather than the address of it. Try the following:

int f1(int ** b) {
    *b = malloc(sizeof(int)); 
    **b = 5;
}

int main() {
    int * a;
    f1(&a);
    printf("%d\n", *a);
    return 0;
}

By passing the pointer value as you were, there was no way for the value malloc created to be stored into the pointer.

Dusty
This is again pass by value. u r passing the address of a by value. **There is no pass by reference in C**
echo
Fair enough. Updated to be more accurate in C.
Dusty
A: 

The address int *b is deleted when the function return. To save it, you need to use a pointer of a pointer

int f1(int ** b) {
   *b = malloc(sizeof(int));
   **b = 5;
}
Phong
+6  A: 

It looks like you're misunderstanding a fundamental part of how C works - namely that it is a 'pass-by-value' language. In order for main() to know about the memory you allocated, you have to get it back out. The following code will do you what you want:

int f1(int **b)
{
    *b = malloc(sizeof(int));
    **b = 5;
}

int main(int argc, char **argv)
{
    int *a;
    f1(&a);
    printf("%d\n", *a);
    return 0;
}

There are a couple differences between this code and yours; first, the signature of f1() has changed, so that it can return the result of the malloc() call in the passed in pointer. Next, the call to f1() has been changed to pass the address of a rather than a itself - important if you want it to be 'filled-in' by f1(), so to speak. Finally, the printf() in main() has been changed to print out the pointed-to value rather than the pointer itself.

Carl Norum
I'm at a loss why everyone has jumped straight to using a pointer-to-a-pointer - that's hardly the best way to explain how to do this to someone who's having trouble with a more fundamental part of the language. Why not just return the pointer from `f1()`?
caf
@caf, yes! that's simple for a beginner to understand.!
echo
Thanks a lot for the feedback everyone! My code works now. I can't have the function return the pointer, because the function in my actual project it is already returning something else..Thanks again!
PM
@caf, this is a fundamental of the C language, why *wouldn't* explaining the pointer-to-a-pointer concept be useful here?
Mark E
I just think it adds needless complication to the explanation, which at heart is that the pointer value needs to somehow be returned to the higher scope. Anyway, this equine is now deceased - there is no sense flogging it any further.
caf
Hi @Mar, may I ask why you did not add in the free(a)?
Yijinsei
+9  A: 

Yes! a is passed by value so the pointer b in function f1 will be local.. either return b,

int *f1() {
    int * b = malloc(sizeof(int));
    *b = 5;
    return b;
}

int main() {
    int * a;
    a = f1();
    printf("%d\n", *a);
    // keep it clean : 
    free(a);
    return 0;
}

or pass a's address

int f1(int ** b) {
    *b = malloc(sizeof(int)); 
    **b = 5;
}

int main() {
    int * a;
    f1(&a);
    printf("%d\n", *a);
    // keep it clean : 
    free(a);
    return 0;
}
echo
+2  A: 

Lets suppose you assign a value of NULL to a before you call function f1. Now the way f1 is defined it takes its argument(pointer to an int) by value. That is b will be another variable of type int * which will be a copy of a. So b too will have a value of NULL. Now in f1 you change the value by b by assigning it the address of memory allocated dynamically using malloc. Lets say that memory address is 0x123. As a result of this assignment, b has changed its value from NULL to 0x123 but a(in main) continues to hold NULL, because changing b will not change a, as they are two separate variables. As a result of this when you return from function f1 a will remain unchanged.

There are 2 ways to solve this. One you can make the function f1 return the value of the changed b and then assign it back to a in main and two, you can pass the a by address so that any changes made in f1 will affect a in main too.

// f1 now returns the value of b.
int* f1() {
 int *b = malloc(sizeof(int));
 *b = 5;
 return b;
}

int main() {
 int *a = NULL;
 a = f1(); // assign the return value of f1 to a.
 printf("%d\n", *a); // prints 5...not its *a not just a.
 return 0;
}

.

// f1 now takes the address of a. 
void f1(int **b) {
 *b = malloc(sizeof(int)); // you are actually altering a indirectly.
 **b = 5; 
}

int main() {
 int *a = NULL;
 f1(&a); // now pass the address of a to f1.
 printf("%d\n", *a); // prints 5...not its *a not just a.
 return 0;
}
codaddict