调用具有文字值的函数时,内存中会发生什么?

时间:2012-06-11 22:29:51

标签: c++

假设我有一个任意函数:

void someFunc(int, double, char); 

我打电话给someFunc(8, 2.4, 'a');,究竟发生了什么? 8,2.4和'a'如何获取内存,移入该内存,并传递给该函数?编译器对这些情况有什么类型的优化?如果我混合和匹配参数,例如someFunc(myIntVar, 2.4, someChar);

,该怎么办?

如果函数声明为inline会怎样?

2 个答案:

答案 0 :(得分:4)

值是文字与否没有区别(除非函数被内联,然后编译器可以优化一些东西)。

通常,参数被放入寄存器或函数参数堆栈中。无论它们是显式值还是变量。

没有优化,参数会被推送到参数堆栈。在第一种情况下,首先获取x的值并将其放入寄存器eax,然后将其推入参数堆栈。 foo打印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 

通过优化,编译器可以看到该函数(在我的示例中),并且完全跳过调用:

    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定义为:

void foo(int x)
{
   std::cout << x;
}

答案 1 :(得分:1)

通常 C ++函数在堆栈上工作。我会在没有优化的情况下描述C calling convention

它会将'a'放在堆栈顶部。然后它将2.4置于堆栈顶部,然后将8置于堆栈顶部,然后为返回类型 [1] 添加空间,然后指令调用函数中当前指令的指针,然后跳转到被调用函数代码的开头 被调用的函数将查看堆栈,获取参数,执行它的操作,将结果放在堆栈上提供的空间中,最后跳转到堆栈上指向的指令(可能是下一条指令)调用它的函数)。既然处理器再次执行调用函数,它会将结果复制到任何需要的地方,并将所有其他内容从堆栈中弹出。*

other calling conventions(其中许多将保留寄存器中的参数)以节省时间,当然,由于例外,还有其他并发症。根据调用函数,它可以内联调用,它会跳过列出的所有步骤,直接执行带有这些常量的被调用函数,或者在 very 高级编译器中执行,在某些情况下,它可能会创建具有硬编码参数的函数的副本,并将该版本称为无参数。

正如我所说,这是我多年前学到的理论。 Luchian Grigore's answer有很多简洁的细节。

[1]维基百科告诉我,如果结果是单个int,则它会在寄存器而不是堆栈中返回。

相关问题