Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does function ACTUALLY return struct variable in C?

Tags:

c

struct

How does a function return value is clear to me, just to kick start:

int f() {   int a = 2;   return a; } 

Now a gets the memory in stack and its life-span is within the f() in order to return the value it copies the value to a special register which is read by the caller as it knows that the callee have placed the value for him. (Since the size of return-value-holder special register size is limited that's why we cant return large objects therefore In case of advance languages when we want to return object function actually copies the address of object in heap to that special register)

Lets come back to C for a situation when i want to return a struct variable not pointer:

struct inventory {     char name[20];     int number; }; struct inventory function();  int main() {     struct inventory items;     items=function();     printf("\nam in main\n");     printf("\n%s\t",items.name);     printf(" %d\t",items.number);      getch();     return 0; }  struct inventory function() {     struct inventory items;     printf(" enter the item name\n ");     scanf(" %s ",&items.name );     printf(" enter the number of items\n ");     scanf("%d",&items.number );     return items; } 

Code forked from: https://stackoverflow.com/a/22952975/962545

Here is the deal,

Lets start with main, items variable declared but not initialized and then function is called which return initialized structure variable which gets copied to the one in main. Now I am bit blurred to understand how function() returned struct variable items which is not dynamically created(technically not in heap) so this variable's life-span is within the function() body, also size of variable item can be huge enough not to fit in special register so why it worked?.(I know we can dynamically allocate item inside function and return the address but I don't want alternative, I am looking for explanation)

Question: Although it works but how does function() actually returned the struct variable and get copied to items variable in main when it is supposed to die with function() return.

I am surely missing important thing, detailed explanation would help. :)

EDIT: Other Answer References:

  1. https://stackoverflow.com/a/2155742/962545
  2. Named as return value optimization
like image 361
gitesh.tyagi Avatar asked Apr 09 '14 08:04

gitesh.tyagi


People also ask

How can a function return a structure in C?

Return struct from a function Here, the getInformation() function is called using s = getInformation(); statement. The function returns a structure of type struct student . The returned structure is displayed from the main() function. Notice that, the return type of getInformation() is also struct student .

Can you return structure variable from function?

One of them asked if you could return a struct from a function, to which I replied: "No! You'd return pointers to dynamically malloc ed struct s instead."

IS function can return structure in C True or false?

Functions can return structure in C? Explanation: None.


1 Answers

Details vary widely by calling convention. Some ABIs have no calling convention for passing whole structures, in which case the compiler is free to do whatever it thinks makes sense.

Examples include:

  • Passing and returning the entire struct as a series of consecutive registers (often used with "small" structs)
  • Placing the entire struct as an argument block on the stack
  • Allocating an empty argument big enough to hold the struct, to be filled with a return value
  • Passing the (stack) address of the struct as an argument (as if the function was declared void function(struct inventory *))

Any of these implementations could conform to the C spec here. But, let's look at a specific implementation: the output from my GCC ARM cross-compiler.

Compiling the code you gave gives me this:

main:     stmfd   sp!, {fp, lr}     add fp, sp, #4     sub sp, sp, #48     sub r3, fp, #52     mov r0, r3     bl  function(PLT) 

Destination operands are always on the left. You can see that the program reserves stack space, then passes the address of the stack space as r0 (the first argument in the ARM EABI calling convention). function takes no arguments, so this argument is clearly an artificial argument added by our compiler.

function looks like this:

function:     stmfd   sp!, {r4, fp, lr}     add fp, sp, #8     sub sp, sp, #36     str r0, [fp, #-40]     ldr r3, .L6          ...     add r2, pc, r2     mov r0, r2     mov r1, r3     bl  scanf(PLT)     ldr r3, [fp, #-40]     mov ip, r3     sub r4, fp, #36     ldmia   r4!, {r0, r1, r2, r3}     stmia   ip!, {r0, r1, r2, r3}     ldmia   r4, {r0, r1}     stmia   ip, {r0, r1}     ldr r0, [fp, #-40]     sub sp, fp, #8     ldmfd   sp!, {r4, fp, pc} 

This code basically stashes the single argument in [fp, #-40], then later loads it and begins stashing data at the address it points to. At the end, it returns this pointer value in r0 again. Effectively, the compiler has made the function signature into

struct inventory *function(struct inventory *) 

where the returned structure is allocated on the stack by the caller, passed in, and then returned.

like image 131
nneonneo Avatar answered Oct 30 '22 13:10

nneonneo