Reputation: 4388
Suppose I have an arbitrary function:
void someFunc(int, double, char);
and I call someFunc(8, 2.4, 'a');
, what actually happens? How does 8, 2.4, and 'a' get memory, moved into that memory, and passed into the function? What type of optimizations does the compiler have for situations like these? What if I mix and match parameters, such like someFunc(myIntVar, 2.4, someChar);
?
What happens if the function is declared as inline
?
Upvotes: 1
Views: 1144
Reputation: 66952
Generally C++ functions work on the stack. I'll describe the C calling convention as it works without optimizations:
It will put 'a'
on top of the stack. Then it puts 2.4
on top of the stack, then it puts 8
on top of the stack, then it adds space for the return type[1], then the instruction pointer of the current instruction in the calling function, and then jumps to the beginning of the called function's code.
The called function will look at the stack, grab the parameters, do it's thing, put the result in the space provided on the stack, and finally jump to the instruction pointed at on the stack (which is presumably the next instruction of the function that called it). Now that the processor is executing the calling function again, it will then copy the result wherever it wants it, and pop all the other stuff off the stack.*
There are other calling conventions (many of which will keep parameters in registers) to save time, and of course, there's other complications due to exceptions. Depending on the calling function, it may inline the call, which skips all of the steps listed and just executes the called function with those constants directly, or in a very advanced compiler and in certain conditions, it might create a copy of the function that has those parameters hardcoded in, and call that version instead parameterless.
As I said, this is all theory I learned years ago. Luchian Grigore's answer has lots of neat details.
[1] Wikipedia informed me that if the result is a single int
, it's returned in a register instead of the stack.
Upvotes: 1
Reputation: 258618
It makes no difference that the values are literal or not (unless the function is inlined and then the compiler can optimize some stuff out).
Usually, parameters are put into registers or the function parameter stack. Regardless of whether they are explicit values or variables.
Without optimizations, the parameter gets pushed onto the parameter stack. In the first case, the value of x
is taken first and put into register eax
, then pushed into the parameter stack. foo
prints x
.
foo(x);
00361A75 mov eax,dword ptr [x]
00361A78 push eax
00361A79 call get_4 (3612B7h)
00361A7E add esp,4
foo(3);
00361A81 push 3
00361A83 call get_4 (3612B7h)
00361A88 add esp,4
With optimizations the function is visible to the compiler (in my sample) and the call is skipped altogether:
foo(x);
01011000 mov ecx,dword ptr [__imp_std::cout (101203Ch)]
01011006 push 3
01011008 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (1012038h)]
foo(3);
0101100E mov ecx,dword ptr [__imp_std::cout (101203Ch)]
01011014 push 3
01011016 call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (1012038h)]
foo
is defined as:
void foo(int x)
{
std::cout << x;
}
Upvotes: 4