6

I know that coding with C, the return value of a function return to caller using %eax register.

With c++ it is also possible to return structs and not just 'Primitive' types, so when a function returns a struct, where is the returned value stored (stack, heap, etc)?

Example Code:

class Student
{
private:
    int m_id;
public:
    Student(int id)
    {
        m_id = id;
    };
    ~Student();
    int getId()
    {
        return m_id;
    };
};

Student myFunc()
{
    return Student(123);
}

int main()
{
    //How does 'student1' get the value from the function?
    //Does 'myFunc' write directly to the stack of main?
    Student student1 = myFunc();


    return 0;
}
Passer By
  • 19,325
  • 6
  • 49
  • 96
iso532
  • 81
  • 5
  • AFAIK that depends on the type of call , and thereafter its an implementation detail. – Hatted Rooster May 30 '18 at 09:15
  • 14
    You can return structs in C as well. – molbdnilo May 30 '18 at 09:17
  • @SombreroChicken - You mean that it can change with different architectures? – iso532 May 30 '18 at 09:17
  • 1
    Even single architecture can have many calling conventions. – user694733 May 30 '18 at 09:19
  • 1
    This question is super unclear. Please provide context and more explanation of the answer that you are trying to find. – Fantastic Mr Fox May 30 '18 at 09:19
  • I will add a code – iso532 May 30 '18 at 09:21
  • Even within a particular calling convention, the exact passing is defined by other factors like size of the `struct` etc. You need to read the ABI document to know the exact way of passing or returning arguments. – Ajay Brahmakshatriya May 30 '18 at 09:26
  • "(stack, heap, etc)?" what's etc here? Are you just asking is the memory on the stack or heap for a return value for a function? – UKMonkey May 30 '18 at 09:31
  • 1
    If the struct is small, it might very well fit in the `eax` register. – Bo Persson May 30 '18 at 09:34
  • 4
    Depends on architecture, ABI, compiler, compiler flags, etc. It's generally either in register(s) (if the structure is small enough) or on stack, like a local variable. – yeputons May 30 '18 at 09:38
  • @UKMonkey - Yes. but also if it on the stack, so where? on the caller stack or in other place? – iso532 May 30 '18 at 09:39
  • 3
    A function doesn't have its own stack. A thread does - meaning "where" on the stack is a question that doesn't really make any sense – UKMonkey May 30 '18 at 09:43
  • 1
    related: [Calling convention for function returning struct](https://stackoverflow.com/questions/4931195/calling-convention-for-function-returning-struct) – Lanting May 30 '18 at 09:55
  • @UKMonkey - I meant which function allocates the memory for that. But anyway PSkocik's answer explain that. – iso532 May 30 '18 at 10:13
  • there are already tons of related and duplicate questions: [C++ on x86-64: when are structs/classes passed and returned in registers?](https://stackoverflow.com/q/42411819/995714), [C/C++ returning struct by value under the hood](https://stackoverflow.com/q/39068492/995714), [How do C compilers implement functions that return large structures?](https://stackoverflow.com/q/2155730/995714), [how c compiler treats a struct return value from a function, in ASM](https://stackoverflow.com/q/24741218/995714), [How does C return a structure?](https://stackoverflow.com/q/6731140/995714) – phuclv May 30 '18 at 16:58
  • [How does function ACTUALLY return struct variable in C?](https://stackoverflow.com/q/22957175/995714), [Return value via stack/register question(https://stackoverflow.com/q/5366121/995714), [Where are returned values stored?](https://stackoverflow.com/q/50600800/995714) – phuclv May 30 '18 at 16:59

1 Answers1

8

In C this depends on the ABI of the platform.

On x86_64 linux, there are several classes of data types but in simple terms, small simple structs (~ <= 2 longs) are returned in registers and large ones through the stack.

The latest C++ should guarantee RVO (Return Value Optimization) I believe, which means structs/classes should get allocated on the stack in the caller and the callee should "secretly" write to them via a pointer (C ABIs/compilers can do this too, but in C++, RVO additionally avoids destruction and copy-construction).

You can always look at the assembly or write a benchmark to verify the passing convention.

(In my opinion, it is, however, best to limit oneself to simple return types in C so you don't have to worry. (Original C didn't even allow one to return structs.) In C++ with RVO it shouldn't matter.)

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • 1
    _'[...] should "secretly" write to them via a pointer'_: In fact, most popular compilers do it that way. Check https://godbolt.org/g/WhFjMP for the output of different compilers on x86-64: almost always a pointer to RBP + offset is returned as in `mov eax, DWORD PTR [rbp-4]`. – andreee May 30 '18 at 09:56