C/C++语言之函数参数栈管理

时间:2022-06-04 12:39:38

   我们知道C语言的基本组成单元是函数,各个函数之间可以相互引用。而函数的参数值,局部变量都是放到栈中管理。所以了解栈的管理工作是非常必要的。而对栈的管理工作中,我们最关心的就是函数参数及局部变量的入栈顺序。

 

     我们调用一个函数,执行过程发生跳转,必然要把必要的寄存器入栈。然后把参数入栈,接着把局部变量入栈。执行完程序之后再把这些反序出栈。注:如果熟悉汇编的话写个函数看它的汇编代码就很容易理解。

这里我们只要知道:

1、函数参数先入栈,之后才到函数局部变量入栈。

      下边是在VC++2005里的一个测试代码:

int fuc1(int a, char ch, int c, double d)
{
 int n1 = 1;
 int n2 = 2;
 printf("Param: &a = 0x%08x, &ch  = 0x%08x, &c = 0x%08x, &d = 0x%08x/n", &a, &ch, &c, &d);
 printf("Value: &n1 = 0x%08x,&n2 = 0x%08x/n", &n1, &n2);
 return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
 fuc1(32, 'a', 3, 1.0);
 system("pause");
 return 0;
}

 

这个函数的功能是在函数里输出参数和局部变量的地址。

结果是:

Param: &a = 0x0013fe7c, &ch  = 0x0013fe80, &c = 0x0013fe84, &d = 0x0013fe88
Value: &n1 = 0x0013fe6c,&n2 = 0x0013fe60

因为局部变量的地址都比参数的变量小。再由第一条结论结合可得到:

2、这机器的栈是向上增长的(入栈后地址向低地址偏移)。

 

由于先声明的局部变量的地址比较大(&n1  < &n2 )。所以得到:

3、先声明的局部变量先入栈。

 

又因为函数参数右边的地址比左边的地址大(&a < &ch  < &c < &d)所以:

4、函数参数的入栈顺序是由右向左。

 

由上面四点结论再加上生命周期的概念就概括出一条重要的结论:

5、生命周期越长则它就越先入栈。

 

结论:函数参数的入栈顺序是由右到左, 变量的生命周期越长就越先入栈。

 

下面就用上面的结论解决实际的问题:

一、栈的生长方向问题。

     找到两个变量,根据它们的地址值的大小及生命周期的大小可很容易判断。 简单的讲,声明两个变量。N, M,(N先声明)当&N>&M时栈向低地址生长; 反之向高地址生长。

二、printf的问题:

     int i = 1;
     printf("%d/t%d/t%d/n", i, i++, i++);  //输出的结果是3,2,1

     i = 1;
     printf("%d/t%d/t%d/n", i, ++i, i++);  //输出的结果是3,3,1

     i = 1;
     printf("%d/t%f/t%d/t%d/n",i,i+1, i+2, i+3);//输出1     0.000000      4     1446776