1

My question is in the context of C programming and NOT C++! I am trying to pass a pointer between multiple function. However the memory allocation should not be done by the caller. I tried a small example to simulate this. As can be seen, when the pointer points to a struct variable defined in main function, it is 'working' as expected. That is my function can manipulate the value in that memory address when the value of the address is passed. However when the function call returns and control passes on to main, why does the pointer get 'reinitialized'? Can the pointer somehow reflect the address that it was pointing to?

How can this be done?

Here is what I have:

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

//example to pass a struct to void pointer and a void pointer to struct
//testing if memory allocation is done by callee and not caller

typedef struct mystructure{
    int a;
    char b;
    unsigned char c[10];
}mystruct;


void func(void *var){

    mystruct *s = var;
    s->a = 100;
    s->b = 'I';
    strncpy(s->c,"test",5);
    printf("In func\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
}

void voidOut(void *var){

    mystruct *s = var;
    printf("In voidOut\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);

}

//here is void pointer is both and 'in' and 'out' parameter
void memfunc(void *var){

    mystruct *s = var;
    s = (mystruct *)malloc(sizeof(mystruct));
    s->a = 100;
    s->b = 'I';
    printf("In memfunc\n");
    strncpy(s->c,"test",5);
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
}

//here is void pointer is an 'in' parameter
void memvoidOut(void *var){

    mystruct *s = var;
    printf("In memvoidOut\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
}


int main(int argc, char *argv[]){
    mystruct val;
    func(&val);
    voidOut(&val);

    mystruct *ptr = NULL;
    memfunc(ptr);
    memvoidOut(ptr);

    return 0;
}

UPDATE: Following the answers and comments, here is what I have:

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

//example to pass a struct to void pointer and a void pointer to struct
//testing if allocation is done by callee and not caller

typedef struct mystructure{
    int a;
    char b;
    unsigned char c[10];
}mystruct;


void func(void *var){

    mystruct *s = var;
    s->a = 100;
    s->b = 'I';
    strncpy(s->c,"test",5);
    printf("In func\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
}

void voidOut(void *var){

    mystruct *s = var;
    printf("In voidOut\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);

}


//here is void pointer is both and 'in' and 'out' parameter
void memfunc(void **var){

    mystruct *s = var;
    s = (mystruct *)malloc(sizeof(mystruct));
    s->a = 100;
    s->b = 'I';
    printf("In memfunc\n");
    strncpy(s->c,"test",5);
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
    //memcpy(var,s, sizeof(s));
}

//here is void pointer is an 'in' parameter
void memvoidOut(void **var){

    mystruct *s = var;
    printf("In memvoidOut\n");
    printf("s->a = %d\n",s->a);
    printf("s->b = %c\n",s->b);
    printf("s->c = %s\n",s->c);
}


int main(int argc, char *argv[]){
    mystruct val;
    func(&val);
    voidOut(&val);

    mystruct *ptr = NULL;
    memfunc(&ptr);
    memvoidOut(&ptr);

    return 0;
}

However my output is:

In func
s->a = 100
s->b = I
s->c = test
In voidOut
s->a = 100
s->b = I
s->c = test
In memfunc
s->a = 100
s->b = I
s->c = test
In memvoidOut
s->a = 0
s->b = d
s->c = 

What am I missing? Shoud I define memory for the struct in memvoidOut?

5
  • Why are you using void pointers? Commented Jan 21, 2016 at 9:47
  • When I explicitly do I memcpy(var,s,sizeof(s)) in memfunc, it works. However I would like to understand what is really happening Commented Jan 21, 2016 at 9:47
  • I want to hide my structure later for developing an API Commented Jan 21, 2016 at 9:49
  • Why not change void memfunc(void *var) to void *memFunc()....return s; Commented Jan 21, 2016 at 9:50
  • Actually I should later use integers as return values to return just error codes.... Commented Jan 21, 2016 at 9:51

2 Answers 2

4

You should change the signature of the function that allocates the new memory:

void memfunc(void *var)

to

void memfunc(void **var)

and call from main

memfunc(&ptr)

Explanation:

Your memfunc function, makes a copy of the passed pointer ptr. Initially, it assigns this pointer to the allocated space (via malloc), but then, after the function returns, the pointer is still the original one that was passed to memfunc (that is NULL) because that ptr pointer's copy was reclaimed.

Now if you change it as proposed, the address of the pointer will be passed, thus you will not face that "copy pointer" issue

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks but I just added a comment: When I explicitly do I memcpy(var,s,sizeof(s)) in memfunc, it works
memcpy has nothing to do with your function. It is a tottaly different approach
Oh I see. thanks for pointing out that the pointer passed is a copy!! That explains
Np, happy to help :)
In parameter meaning that you want to pass something other than null? And make some calculations before assigning new memory to it? Yes that should be doable too.
|
1

Function arguments are passed by value in C. So, you cannot pass the pointer itself and allocate memory to the pointer itself from the called function.

You can do either of two things

  1. Pass the address of the pointer to allocated memory from another function.

  2. Pass the pointer, allocate memory, return the allocated pointer from the function and in the caller, collect the return value in the same pointer.

So, in case of memfunc(), either

  • You have to change the signature to pass &ptr, collect in mystruct **var and then, inside the function, allocate memory for *var

  • You need to return a mystruct * and collect that in ptr.

2 Comments

In void memfunc(void *var) I was hoping to somehow keep the var parameter as both the 'input' and 'output' parameter
Sourav Ghosh, could you please explain the second method. Can I keep the returned structure in the void pointer itself. Can you please elaborate

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.