Home > Software design >  How to return a stack object from a function and then use a pointer to hold its address?
How to return a stack object from a function and then use a pointer to hold its address?

Time:10-09

Normal C functions cannot return the address of the stack object inside the function, because the object is destroyed along with the stack frame when the function returns.

Here is the incorrect code.

int* fun(void) {
    int tmp = -1;
    return &tmp;
}

In general, the right thing to do is to allocate on the heap.

int* fun(void) {
    int* tmp = malloc(sizeof(int));
    if (tmp != NULL) {
        *tmp = -1;
    }
    return &tmp;
}

The problem with this approach, however, is that it requires the caller to free memory manually. So I would like to see if some simpler structures, such as an iterator (defined as a smaller structure, for example), can be allocated on the stack. The code looks something like this.

int function_int(void) {
    return -1;
}

#define function_int_wrapper()  &(int){function_int()}
int* ptr = function_int_wrapper();

The advantage is that the object the pointer points to is on the stack, so there is no need to manually free it.

typedef struct {
    int id;
}st;

st function_st(void) {
    return (st){-1};
}

#define function_st_wrapper()   &(st){function_st()}
st* ptr = function_st_wrapper();

This can be done by using {} and casting to define a local stack variable after the function returns. The same code does not work on constructs. Even though the members of the structure also have only one int.

CodePudding user response:

Why do you want a pointer? Your function_st returns a struct, so store it as such

st val = function_st();

You can later make a pointer to it by using &val, but there's no reason to create a pointer variable, or try to create an anonymous object rather than a named object.

CodePudding user response:

Thank you very much for your reply. I have found a solution.

#define function_st_wrapper() (st[1]){function_st()}

st* ptr = function_st_wrapper();

I need Pointers for a strange reason, because _Generic needs to be syntactically correct for all branches, so I have to use structure Pointers instead of using structure instances directly. At the same time, I wanted the code to be as clean as possible.

  • Related