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

参数入栈顺序:

调用约定:

gcc语言默认使用__cdecl调用约定。调用约定不是语言的一部分,是编译器的一部分。

调用约定使用的最典型的地方就是库函数的调用。因为库的编译方式我们的自己的程序的编译方式可能不一样。

小问题:

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

示例程序:

 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 }

这里我们求平均值的时候还需要定义数组,那么有没有一种方法,我们不定义数组,而是直接将要求的数的当做参数传进去呢?

那就得使用可变参数函数了。

可变参数:

示例程序:

 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 }

第四行程序中中的...就是代表可变参数。

va_list是stdarg.h中的一种数据类型,第6行通过va_list可以得到这些可变参数。

第10行表示我们现在要从args中取值了,第17行表示取值结束。

运行结果如下:

printf也是可变参数函数,它并没有规定有多少个参数,但是规定了第一个参数必须是一个字符串。这个字符串可以是格式化的字符串。

字符串中的格式化字符%d、%f就是用来统计可变参数个数的。

可变参数的限制:

printf中当看到%d的时候就知道这个位置应该取出一个int型变量。

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9562930.html

时间: 2024-10-06 14:38:49

第45课 函数参数的秘密(下)的相关文章

第44课 函数参数的秘密 (上)

函数参数: 函数参数的求值顺序依赖于编译器的实现: 第一感觉,这个函数会输出1和2,k的最终值会变成3. 示例程序: 1 #include <stdio.h> 2 3 int func(int i, int j) 4 { 5 printf("%d, %d\n", i, j); 6 7 return 0; 8 } 9 10 int main() 11 { 12 int k = 1; 13 14 func(k++, k++); 15 16 printf("%d\n&q

第44课 函数参数的秘密(上)

1. 函数参数 (1)函数参数在本质上与局部变量相同,都在栈上分配空间 (2)函数参数的初始值是函数调用时的实参值 (3)函数参数的求值顺序依赖于编译器的实现(注意:这里指求值顺序而不是入栈顺序!) [实例分析]函数参数的求值顺序 #include <stdio.h> int func(int i, int j) { printf("i = %d, j = %d\n",i, j); return 0; } int f() { printf("f() Call...

第7课 函数参数的扩展

1.  函数参数的默认值 (1)C++中可以在函数声明时为参数提供一个默认值(注意是声明,不能在定义中提供) (2)当函数调用时没有提供参数的值,则使用默认值 [实例分析]默认参数值初探 #include <stdio.h> //默认值只能在函数声明时提供 int mul(int x = 0); //参数x的默认值为0 int main() { printf("%d\n", mul()); //传入默认值0 printf("%d\n", mul(-1))

AGG第六课 函数参数使用弧度

2.1 定义 所谓"弧度的定义"就是说,1弧度的角大小是怎样规定的? 我们知道"度"的定义是,"两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧.当这段弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度. 那么,弧度又是怎样定义的呢? 弧度的定义是:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧.当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧 摘自:http://sourceforge.net/p/vector-agg

python下函数参数的传递(*和**)

1.F(arg1,arg2,...) 这 是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的 值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参.例 如: def a(x,y): print x,y 调用该函数,a(1,2)则x取1,y取2,形参与实参相对应,如果a(1)或者a(1,2,3)则会报错. 2.F(arg

JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y); }; var sum = function(x, y) { return x + y; }; var diff = function(x, y) { return x - y; }; var sumResult = calculate(1, 2, sum), diffResult = calcu

如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如何在命令长度受限的情况下成功get到webshell,以及关于函数参数受限的突破,mysql的一些骚操作技巧~~~ 0x02 问题分析 我们先看个例子: <?php $param = $_REGUEST['param']; if(strlen($param) < 17){ eval($param)

第9课 函数重载分析(下)

1. 重载与函数指针 (1)将重载函数名赋值给函数指针时 ①根据重载规则挑选与函数指针参数列表一致的候选者 ②严格匹配候选者的函数类型与函数指针的函数类型(所谓严格匹配,即函数参数及返回值都匹配) [编程实验]函数重载 VS 函数指针 #include <stdio.h> #include <string.h> int func(int x) { return x; } int func(int a, int b) { return a + b; } int func(const

第20课 可变参数模板(1)_模板参数包和函数参数包

1.  参数包(parameter pack) (1)模板参数包(以tuple为例):template<typename- Elements>class tuple ①Elements标识符的左侧使用了省略号,在C++11中Elements被称为"模板参数包",表示可以接受任意多个参数作为模板参数. ②编译器将多个模板参数打包成"单个"的模板参数包,如tuple<int, char, double>实例化模板类时,Element就是包含int