I have a general doubt regarding passing pointers to functions...

Suppose i have variable

tc_struct *ptr;

and i want to pass it to a function to fill it. So i passed it

func(&ptr);

and i received it in func as

void func(tc_struct** ptr1)

Now again i want to pass this same pointer to another function from inside 'func' to fill some part of the structure. So should i pass it as

func2(&ptr1)

and receive as

void func2(tc_struct*** ptr2)

or is it ok if i pass it as

func2(ptr1)

and receive as

void func2(tc_struct** ptr2)

In which method i can get allt he modifications inside func2 reflected inside my actual pointer ptr?

note :these functions could go in a nested way to say funcN()..


-----


I want to know if there is any generic idea i can apply on pointer to functions.

Thanks in advance

Pass it as in the second example: void func2(tc_struct** ptr2) Its not necessary to add more stars and pointers to pointers to pointers ...

Pass it as in the second example: void func2(tc_struct** ptr2) Its not necessary to add more stars and pointers to pointers to pointers ...

Thank you..
could you please explain the reason also in detail...

Thank you..
could you please explain the reason also in detail...

If you want to see the reasoning, try verifying the addresses that your passing.

start with the original address, then verify it in the first function and then verify that its the same in the second function.

thanks for the reply.

i understood the solution but i want to know how does it work.


I will explain what i know here. whenever we allocate to a function uisng malloc(linux/gcc perspective) it goes to heap. since heap is global scope, we will get the value even if we are exiting a function in which the memory is allocated(lets say i am allocating memory to that pointer inside func). So even if we dont pass the address of that pointer and we allocate it inside the called function(func), the memory should be available in the calling function(function which calls func).

Then why we need to pass the address of a pointer to the called function
(func)?
please correct me if i am wrong.

and can anyone explain the solution in the memory perspective??

thanks in advance

Do you understand the following?

#include <stdio.h>

void foo(int copy)
{
   printf("copy = %d\n", copy);
   copy = -5;
   printf("copy = %d\n", copy);
}

void bar(int *ptr)
{
   printf("*ptr = %d\n", *ptr);
   *ptr = -5;
   printf("*ptr = %d\n", *ptr);
}

int main(void)
{
   int value = 42;
   printf("value = %d\n", value);
   foo(value);
   printf("value = %d\n", value);
   bar(&value);
   printf("value = %d\n", value);
   return 0;
}

/* my output
value = 42
copy = 42
copy = -5
value = 42
*ptr = 42
*ptr = -5
value = -5
*/

The function foo() receives a copy. Modifying the copy does not change the value passed to it in the calling function. If you want to change the value in foo(), you can pass a pointer to the value. Then modifying the pointed-to integer in the called function will change the value in the calling function.

Expand this example to a pointer. You need to then pass a pointer to a pointer to change the pointed-to value (which is itself a pointer) in the called function.

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

int global = 100;

void foo(int *copy)
{
   printf("copy = %p\n", (void*)copy);
   copy = &global;
   printf("copy = %p\n", (void*)copy);
}

void bar(int **ptrtoptr)
{
   printf("*ptrtoptr = %p\n", (void*)*ptrtoptr);
   *ptrtoptr = malloc(sizeof **ptrtoptr);
   printf("*ptrtoptr = %p\n", (void*)*ptrtoptr);
}

int main(void)
{
   int value = 42;
   int *ptr = &value;
   printf("ptr = %p\n", (void*)ptr);
   foo(ptr);
   printf("ptr = %p\n", (void*)ptr);
   bar(&ptr);
   printf("ptr = %p\n", (void*)ptr);
   free(ptr);
   return 0;
}

/* my output
ptr = 0022FF54
copy = 0022FF54
copy = 00402000
ptr = 0022FF54
*ptrtoptr = 0022FF54
*ptrtoptr = 00982A40
ptr = 00982A40
*/

HTH

Comments
thanks for the detailed reply

Do you understand the following?

Expand this example to a pointer. You need to then pass a pointer to a pointer to change the pointed-to value (which is itself a pointer) in the called function.

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

int global = 100;

void foo(int *copy)
{
   printf("copy = %p\n", (void*)copy);
   copy = &global;
   printf("copy = %p\n", (void*)copy);
}

void bar(int **ptrtoptr)
{
   printf("*ptrtoptr = %p\n", (void*)*ptrtoptr);
   *ptrtoptr = malloc(sizeof **ptrtoptr);
   printf("*ptrtoptr = %p\n", (void*)*ptrtoptr);
}

int main(void)
{
   int value = 42;
   int *ptr = &value;
   printf("ptr = %p\n", (void*)ptr);
   foo(ptr);
   printf("ptr = %p\n", (void*)ptr);
   bar(&ptr);
   printf("ptr = %p\n", (void*)ptr);
   free(ptr);
   return 0;
}

/* my output
ptr = 0022FF54
copy = 0022FF54
copy = 00402000
ptr = 0022FF54
*ptrtoptr = 0022FF54
*ptrtoptr = 00982A40
ptr = 00982A40
*/

HTH

Hi Dave,
Thanks. I understood the program. In the 2nd example, foo receives only a copy of that address and allocates memory (if thats a malloc instead of copying global address)to that copy. So the main function is not getting it. Correct?

If so, how we can free that memory?

my second doubt is a little bit off the topic.

*ptrtoptr = malloc(sizeof **ptrtoptr);

is this ok? since size of a pointer(**ptrtoptr is a pointer) is always fixed?suppose instead of value(int) we are using a value(char) is it correct??

*ptrtoptr = malloc(sizeof (int));

Is this not the correct method?

thanks

>If so, how we can free that memory?
Assuming the pointer was dynamically allocated in the function (which it wasn't in the case of foo), you either free it within the function or suffer a memory leak.

>since size of a pointer(**ptrtoptr is a pointer) is always fixed?
>suppose instead of value(int) we are using a value(char) is it correct??

That's the whole point of the construct. If you take the size of the pointer object you're assigning to, the type is deduced automatically. Thus, if/when the type of the pointer changes, you don't need to change the call to malloc:

char *a = malloc ( sizeof *a ); // Allocates a char
int *b = malloc ( sizeof *b ); // Allocates an int
double *c = malloc ( sizeof *c ); // Allocates a double

struct coord { int x; int y; };

struct coord *e = malloc ( sizeof *d ); // Allocates a coord

Notice that the call to malloc follows the same pattern, and that the type is only specified in the declaration (not the call to malloc). Compare that with the more traditional way you were using:

char *a = malloc ( sizeof ( char ) ); // Allocates a char
int *b = malloc ( sizeof ( int ) ); // Allocates an int
double *c = malloc ( sizeof ( double ) ); // Allocates a double

struct coord { int x; int y; };

struct coord *e = malloc ( sizeof ( struct coord ) ); // Allocates a coord

Now you have to include the type in two places, which means if the type changes it needs to be changed in two places. This code is still correct, but it's not as easily maintained. Worse yet, you need to be careful about which type you're using in malloc because there's no cross-checking:

/* Gotta be careful to get the right type */
int **p = malloc ( n * sizeof ( int* ) );

for ( i = 0; i < n; i++ )
  p[i] = malloc ( sizeof ( int ) );

This manual cross-checking is unnecessary when sizeof deduces the type from an object:

/* No worries, just follow the pattern of "*lhs" */
int **p = malloc ( n * sizeof *p );

for ( i = 0; i < n; i++ )
  p[i] = malloc ( sizeof *p[i] );

You may be wondering about whether it's a good idea to dereference an uninitialized pointer as the operand to sizeof in the case of T *p = malloc ( sizeof *p ); , but it's perfectly safe. sizeof doesn't evaluate its operand, so you can use expressions that would otherwise be disastrous.

Comments
Thanks for clearing up some fuzz I'd left.
thanks for the detailed reply

ok. thank you.
just confirming that u indented

struct coord *e = malloc ( sizeof *e ); // Allocates a coord

instead of

struct coord *e = malloc ( sizeof *d ); // Allocates a coord

anyway this type of allocation was a new information for me and many thanks for that.

Thank you for all helping me understand this topic better.

regards,

This question has already been answered. Start a new discussion instead.