第45课 - 函数参数的秘密(下)

1、参数入栈顺序 

            函数参数的计算次序是依赖编译器实现的, 

            那么函数参数的入栈次序是如何确定的呢? 



2、调用约定 

            当函数调用发生时 

                -参数会传递给被调用的函数 

                -而返回值会被返回给函数调用者 

            调用约定描述参数如何传递到栈中以及栈的维护方式 

                -参数传递顺序 

                -调用栈清理 


            调用约定是预定义的可理解为调用协议 

            调用约定通常用于库调用库开发的时候 

                -从右到左依次入栈:__stdcall , __cdecl , __thiscall 

                -从左到右依次入栈:__pascal , __fastcall 


                若A编译器是C语言编译器(默认从右到左)B编译器是

                pascal编译器(从左到右),就需要调用约定


3、小问题 

                如何编写—个计算n个数平均值的函数? 


4、实例分析 

编写函数计算平均值     45-1.c 

  1. #include <stdio.h>  
  2.   
  3. float average(int array[], int size)  
  4. {  
  5.     int i = 0;  
  6.     float avr = 0;  
  7.       
  8.     for(i=0; i<size; i++)  
  9.     {  
  10.         avr += array[i];  
  11.     }  
  12.       
  13.     return avr / size;  
  14. }  
  15.   
  16. int main()  
  17. {  
  18.     int array[] = {1, 2, 3, 4, 5};  
  19.       
  20.     printf("%f\n", average(array, 5));  
  21.       
  22.     return 0;  
  23. }  

                        如何实现直接average(1,2,3,4,5)?


5、可变参数 

            C语言中可以定义参数可变的函数 

            参数可变函数的实现依赖于stdarg.h头文件 

                - va_list - 参数集合

                - va_arg - 取具体参数值 

                - va_start - 标识参数访问的开始 

                - va_end - 标识参数访问的结束 


6、实例分析 

编写函数计算平均值     45-2.c

  1. #include <stdio.h>  
  2. #include <stdarg.h>  
  3.   
  4. float average(int n, ...)  
  5. {  
  6.     va_list args;  
  7.     int i = 0;  
  8.     float sum = 0;  
  9.       
  10.     va_start(args, n);  
  11.       
  12.     for(i=0; i<n; i++)  
  13.     {  
  14.         sum += va_arg(args, int);  
  15.     }  
  16.       
  17.     va_end(args);  
  18.       
  19.     return sum / n;  
  20. }  
  21.   
  22. int main()  
  23. {  
  24.     printf("%f\n", average(5, 1, 2, 3, 4, 5));  
  25.     printf("%f\n", average(4, 1, 2, 3, 4));  
  26.       
  27.     return 0;  
  28. }  


                                


7、可变参数的限制 

            可变参数必须从头到尾按照顺序逐个访问 

            参数列表中至少要存在—个确定的命名参数 

            可变参数函数无法确定实际存在的参数的数量 

            可变参数函数无法确定参数的实际类型 

            注意: 

                    va_arg中如果指定了错误的类型,那么结果是不可预测的


8、小结 

            调用约定指定了函数参数的入栈顺序以及栈的清理方式 

            可变参数是C语言提供的—种函数设计技巧 

            可变参数的函数提供了—种更方便的函数调用方式 

            可变参数 必须顺序的访问,无法直接访问中间的参数值 


猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/80198510