0
votes

I wrote this code:

#include<stdio.h>
int valFunc(int val){
     return val;
}


int main(){
     int a  = 5;
     int b = 7;

     printf("%d",valFunc(a)+valFunc(b));

     return 0;

}

Inside the printf() function of main(), after valFunc(a) gets called and returns the value as 5, where does the main function save this value 5 before calling valFunc(b)?

I know that if this function was written like below, then it would have saved the returned values of the functions valFunc(5) and valFunc(7) in integer variables a and b respectively. :

#include<stdio.h>
int valFunc(int val){
     return val;
}


int main(){


  int a = valFunc(5);
  int b = valFunc(7);

  printf("%d",a+b);


  return 0;
}

But in the former code, I am unable to understand where does the function save the returned values? Does it create implicit variables and uses them to save its progress before calling other functions or is there some other mechanism? Please explain.

Does it create any temporary variables to store these values on the runtime stack before calling the other functions? In the second code that I have written in the question, its clear that main() will store these values in a and b and put them on the runtime stack. But how main() will do this for the first code as there are no variables?

2
Thats more like C++ temporary objects, see this: stackoverflow.com/questions/9109831/…ThunderWiring
Please specify one of C and C++ as these two languages have different concepts for what happens in this case. I retagged your question to C as all your code looks like C code.fuz

2 Answers

3
votes

It is very dependent on the system architecture, but in the most general case when a function is called in C the result is returned in a specific register, always the same. If we focalize on Intel X32-64 the return value is passed in the register eax for 32 bits and rax for 64. In this case the code emitted from compiler for an IA32 will be (more or less):

lea eax, a                  //Get parameter address
mov eax, dword ptr [eax]    //Get the value
push eax                    //pass parameter on stack
call valFunc                //call function
mov ebx, eax                //save result in register ebx
lea eax, ba                 //Get parameter address
mov eax, dword ptr [eax]    //Get the value
push eax                    //pass parameter on stack
call valFunc                //call function
add  eax, ebx               //sum the results
push eax                    //pass the sum as parameter on stack
lea eax, fmtstr             //Get the address of the format string "%d"
push eax                    //push it onto the stack
call _printf

As a variation the result can be saved on the stack (i.e. in the case that all registers are in use):

....
call valFunc                //call function
push eax                    //save result on the stack
lea eax, ba                 //Get parameter address
mov eax, dword ptr [eax]    //Get the value
push ebx                    //save ebx on the stack
mov ebx, eax                //save result in register ebx
call valFunc                //call function
add  eax, ebx               //sum the results
pop  ebx                    //Restore register ebx from stack
push eax                    //pass the sum as parameter on stack
....

I hope this clarify the point.

2
votes

Interestingly, you aren't worried about a+b. But it is a very similar thing.

Intermediate values of more complex expressions are stored... somewhere. In a register, in a memory location, on the stack... it's up to the compiler. Yes, you can think of them as temporary variables... but really, they are not your concern.

In the second code that I have written in the question, its clear that main() will store these values in a and b and put them on the runtime stack

It's up to the compiler. It can inspect that you're doing simple operations, directly calculate the final result, which is 12, at compile time, then emit a code which directly calls printf with 12.

It's the as-if rule. As long as your application behaves the same observable way (in this case, prints 12) the compiler can do whatever it wants.