C利用可变参数列表统计一组数的平均值,利用函数形式参数栈原理实现指针运算

//描述:利用可变参数列表统计一组数的平均值
#include <stdarg.h>
#include <stdio.h>

float average(int num, ...);//函数原型;即声明
float average2(int num, ...);//num个数
void add(int num, int x, int y, int z);
int main(void){
	int a=10;
	int b=20;
	printf("a地址:%p b地址:%p\n",&a,&b);
	//宏来实现
	float aver = average(4, 10,20,30,40);
	printf("aver:%.2f\n",aver);
	//调用指针可变参数来实现
	aver = average(4, 10,20,30,40);
	printf("aver2:%.2f\n",aver);

	//调用add
	add(4,20,30,40);
	/*
	输出:说明依次压入栈中的顺序是 可能根据机器不同入栈先后也不同
	从下面输出结果看;高地址 n 先入栈;依次是x,y,最后z入栈
n地址:0x7ffff656d8ac
x地址:0x7ffff656d8a8
y地址:0x7ffff656d8a4
z地址:0x7ffff656d8a0

	*/
	return 0;
}
float average(int val, ...)
{
	//定义一个va_list类型的变量用于访问可变参数类别
	va_list varlist;
	int count;
	float sum = 0;
	//初始化可变参数列表
	va_start(varlist,val);
	//通过循环获取可变参数列表的参数
	for(count=0;count<val;count++){
		sum += va_arg(varlist,int);
	}
	va_end(varlist);

	return sum/val;
}
/*描述:利用函数变量在栈中存储的原理来实现平均数
linux 中函数的参数如 int(int a,int b,int c) 依次是从 右边向左依次
压入栈空间的;所有可以定义一个指针来循环获取每一个可变参数的值
*/
float average2(int num,...)
{
	int* p = #
	float sum = 0;
	int i=1;
	for(; i<num;i++){
		sum += *(p+i);
	}
	return sum/num;
}
//扩展:使用函数栈的原理 利用指针来操作形式参数
void add(int num, int x, int y ,int z)
{
	//形式参数的地址
	printf("n地址:%p\n",&num);
	printf("x地址:%p\n",&x);
	printf("y地址:%p\n",&y);
	printf("z地址:%p\n",&z);

}

  

从上面来看;add函数参数入栈顺序 从左到右LInux 和Windows不一样

进一步发现,Pascal语言不支持可变长参数,而C语言支持这种特色,正是这个原因使得C语言函数参数入栈顺序为从右至左。

具体原因为:C方式参数入栈顺序(从右至左)的好处就是可以动态变化参数个数。

通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。

除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。

这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。

因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式,

C语言中可变参数都是从左到右,所以不管你有多少个参数反正将最右面的那个压入栈底,最左面的参数出入栈顶。换句话说,如果不支持这个特色,

C语言完全和Pascal一样,采用自左向右的参数入栈方式

原文地址:https://www.cnblogs.com/wanglijun/p/8540642.html

时间: 2024-10-17 13:27:16

C利用可变参数列表统计一组数的平均值,利用函数形式参数栈原理实现指针运算的相关文章

创建函数利用可变参数列表的形式模拟实现printf的功能

★创建函数利用可变参数列表的形式模拟实现printf的功能. 模拟简单的输入单个字符和字符串时的输出形式 如:输入:%c %c %c %c %c\t%s,'h','e','l','l','o',"welcome to here!" 输出:h e l l o   welcome to here! #include<stdio.h> #include<stdlib.h> #include<stdarg.h>    //需引入stdarg的头文件以便建立可

使用可变参数列表实现任意个数求平均值

#include <stdio.h> #include <stdarg.h> int average(int val,...) {   int i=0;   int sum=0;   va_list arg;   va_start(arg,val);     for(i=0;i<val;i++)   {     sum+=va_arg(arg, int);   }   va_end(arg);   return sum/val; } int main() {   int re

可变参数列表

函数原型:列出了函数期望收到的参数数目及类型,但是它只能显示"固定数目"的参数. 可变参数列表:让一个函数在不同的时刻接受"不同数目"的参数.可变参数列表是通过宏来实现的,这些宏都在stdarg.h这个头文件中,所以使用可变参数列表时要引用头文件#include<stdarg>. 例如:求寻找一组整数中最小的值,因为整数的个数不确定,所以函数在传参的时候也是不确定的,因此需要用到可变参数列表: 利用可变参数列表求最小值:来看看可变参数列表的形式: int

PHP函数可变参数列表的具体实现方法介绍

PHP函数可变参数列表可以通过_get_args().func_num_args().func_get_arg()这三个函数来实现.我们下面就对此做了详细的介绍. AD:2014WOT全球软件技术峰会北京站 课程视频发布 也许对于PHP初级程序员来说,对于PHP函数并不能完全熟练的掌握.我们今天为大家介绍的PHP函数可变参数列表的实现方法主要是利用func_get_args().func_num_args().func_get_arg()这三个系统函数来实现的,其中func_get_args()

php课外笔记--函数可变参数列表的实现

php课外笔记--函数可变参数列表的实现 php的函数方面非常强大,但对于一些php新手来说,理解有部分困难,不能完全熟练的掌握. php培训教程中,介绍一部分函数可变参数列表的实现方法: PHP函数可变参数列表的实现方法主要是利用func_get_args().func_num_args().func_get_arg()这三个系统函数来实现的,其中func_get_args()函数以数组的形式获得参数列表,具体用法参看手册. PHP函数可变参数列表代码如下: < ?php    /*   函数

可变参数列表的例题

1.使用可变参数列表实现任意个数求平均值. #include<stdio.h> #include<stdarg.h> float average(int val,...) { int i=0; float sum=0.0; float ave=0.0; va_list arg; va_start(arg,val); for(i=0;i<val;i++) { sum+=va_arg(arg,int); } va_end(arg); ave=sum/val; return ave

【转】C++可变参数列表处理宏va_list、va_start、va_end的使用

VA_LIST是在C语言中解决变参问题的一组宏他有这么几个成员: 1)va_list型变量: #ifdef     _M_ALPHA typedef    struct{ char* a0; /*pointertofirsthomedintegerargument*/ int offset; /*byteoffsetofnextparameter*/ }va_list; #else typedef    char* va_list;#endif 2)_INTSIZEOF宏,获取类型占用的空间长度

C++可变参数列表处理宏va_list、va_start、va_end的使用

VA_LIST是在C语言中解决变参问题的一组宏他有这么几个成员: 1)va_list型变量: #ifdef     _M_ALPHA typedef    struct{ char* a0; /*pointertofirsthomedintegerargument*/ int offset; /*byteoffsetofnextparameter*/ }va_list; #else typedef    char* va_list;#endif 2)_INTSIZEOF宏,获取类型占用的空间长度

可变参数列表的实现

在学习C语言的过程中,大家是不是和我一样,认为printf是一个神一样的函数?他可以接受不同数目,不同类型的参数,他到底是怎么实现的呢? 让我们去看一下它的源代码: printf源代码: int printf(const char *fmt,...) { int res; va_list arg; va_start(arg,fmt); res = vprintf(fmt,arg); va_end(arg); return res; } 它采用的是可变参数列表,可变参数列表主要有以下两个缺点: 1