1

I'm new to C, just a question on returning a struct. I hear people saying that it is OK to return a struct. For example:

struct MyObj{
   int x,y,z;
};

struct MyObj foo(){
    struct MyObj foo_a;
    foo_a.x = 10;
    foo_a.y = 10;
    foo_a.z = 10;

    return foo_a;
}        

int main () {
    struct MyObj main_a = foo();
    return 0;
} 

My questions is:

foo_a is in foo's stack, so after the foo finish, the stack will be unwinded, which means foo_a doesn't actually exist in main function's stack, the pointer main_a that main holds is actually an illegal pointer, then how is it going to work?

phuclv
  • 32,499
  • 12
  • 130
  • 417
amjad
  • 3,048
  • 1
  • 11
  • 42
  • 1
    `main holds is actually an illegal pointer` but there are no pointers. `main_a` is not a pointer – KamilCuk Oct 21 '20 at 23:23
  • 3
    It's OK to return a copy of a local variable — you do it all the time with functions that return an `int`. What's not OK is trying to return a pointer to a local variable; a copy of the pointer is returned OK, but the data it points at no longer exists, leading to problems. – Jonathan Leffler Oct 21 '20 at 23:30
  • @JonathanLeffler yes I know that, thats why I was asking why people say it is ok to return a struct without using malloc – amjad Oct 21 '20 at 23:31
  • 2
    Because you're returning a copy of the struct, not a pointer to the struct. Like you return a copy of an `int`, not a pointer to an `int`. – Jonathan Leffler Oct 21 '20 at 23:31
  • @JonathanLeffler sorry I don't get it, do you mean the `foo` fucntion return a copy of the struct by writting values in `main` method 's stack where `main_a` is? – amjad Oct 22 '20 at 02:32
  • More or less, yes. The implementation-level details are up to the implementation, but the net result is that a copy of the structure is made available to the calling function (`main()`) and is assigned to `main_a`. It might be that the compiler passes a pointer to `main_a` to the function and the function copies the local variable over the variable pointed to — but there could be other ways of implementing it too. At one level, all that matters is that the C standard says you can return structures, and the compiler simply has to implement that somehow. – Jonathan Leffler Oct 22 '20 at 03:51
  • duplicates: [How does function ACTUALLY return struct variable in C?](https://stackoverflow.com/q/22957175/995714), [C/C++ returning struct by value under the hood](https://stackoverflow.com/q/39068492/995714), [How does C return a structure?](https://stackoverflow.com/q/6731140/995714), [How do C compilers implement functions that return large structures?](https://stackoverflow.com/q/2155730/995714) – phuclv Oct 24 '20 at 04:16
  • A function can always return its own type. – David C. Rankin Oct 24 '20 at 04:29

1 Answers1

6

A common way this is implemented is that the calling routine allocates some space for the structure, typically on the stack, and passes the called routine a pointer to that space. This parameter is not seen in the C source code—it is part of the calling convention of how routines are called in assembly language. Then the called routine simply stores the contents of the structure in the pointed-to space.

In other words, the code is implemented largely as if it had been written:

void foo(struct MyObj *temporary){
    struct MyObj foo_a;
    foo_a.x = 10;
    foo_a.y = 10;
    foo_a.z = 10;
    *temporary = foo_a;
}        

int main () {
    struct MyObj temporary;
    foo(&temporary);
    struct MyObj main_a = temporary;
    return 0;
} 

If the structure is small, it could be returned in a register, or a few registers. Both the called routine and the calling routine would be using the same calling convention, which would have rules about which structures are returned in registers versus which are returned via a pointed provided by the caller.

Eric Postpischil
  • 168,892
  • 12
  • 149
  • 276
  • sorry still don't get it, `struct MyObj a;` only exist in `foo`'s stack, once foo finishes, it's stack is gone too, so `main_a` is pointing to sth that doesn't exist? – amjad Oct 22 '20 at 02:34
  • I think that the concept you are having difficulty with is that `main_a` is not a pointer. Think of the statement `return foo_a` in your code as performing a copy operation of all the fields in the structure. It is not assigning a pointer to the structure. – DavidHoadley Oct 22 '20 at 02:41