//描述:利用可变参数列表统计一组数的平均值
#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一样,采用自左向右的参数入栈方式
 
 

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

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

    PHP函数可变参数列表可以通过_get_args().func_num_args().func_get_arg()这三个函数来实现.我们下面就对此做了详细的介绍. AD:2014WOT全球软件技术峰会 ...

  2. 可变参数列表与printf()函数的实现

    问题 当我们刚开始学习C语言的时候,就接触到printf()函数,可是当时"道行"不深或许不够细心留意,又或者我们理所当然地认为库函数规定这样就是这样,没有发现这个函数与普通的函数 ...

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

      VA_LIST是在C语言中解决变参问题的一组宏他有这么几个成员: 1)va_list型变量: #ifdef     _M_ALPHA typedef    struct{ char* a0; /* ...

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

    VA_LIST是在C语言中解决变参问题的一组宏他有这么几个成员: 1)va_list型变量: #ifdef     _M_ALPHA typedef    struct{ char* a0; /*po ...

  5. C++实现可变参数列表

    // 接收数量不定的实参.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #includ ...

  6. 可变参数列表---以dbg()为例

    在UART驱动的drivers/serial/samsung.h中遇到如下定义: #ifdef CONFIG_SERIAL_SAMSUNG_DEBUG extern void printascii(c ...

  7. Chapter5_初始化与清理_数组初始化与可变参数列表

    一.数组初始化 数组是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列.编译器是不允许指定数组的长度的,当使用语句int[] a时,拥有的只是一个符号名,即一个数组的引用,并不拥 ...

  8. jdk5可变参数列表

    今天碰到了 public static String getAutoRelateRelationship(final JSONObject modifyJson, String... inUsedCo ...

  9. Java 可变参数列表

    1.可变参数列表的简单实现 当调用方法时,方法的参数个数或类型未知时,称其为可变参数列表.在以前的Java代码中,可以使用Object数组来实现这样的功能.因为,所有的类都是直接或间接继承于Objec ...

随机推荐

  1. 创建包含CRUD操作的Web API接口-第一部

    在这里,我们将创建一个新的Web API项目,它将使用实体框架实现Get,POST.PUT和DELETE方法来实现CRUD操作. 首先,在Visual Studio 2013 for Web expr ...

  2. 不是所有OutOfMemoryError异常都跟内存有关

    一个老鸟遇到一个稀奇的问题后,如果只是想想,那么可能会失去一次丰富自己的机会. 如果从开始养成一个习惯,把所有难解决的问题都记录下来,面试的时候,也可能是给自己一次机会 *************** ...

  3. WPF 不要给 Window 类设置变换矩阵(应用篇)

    原文:WPF 不要给 Window 类设置变换矩阵(应用篇) WPF 的 Window 类是不允许设置变换矩阵的.不过,总会有小伙伴为了能够设置一下试图绕过一些验证机制. 不要试图绕过,因为你会遇到更 ...

  4. 使用springboot实现一个简单的restful crud——01、项目简介以及创建项目

    前言 之前一段时间学习了一些springboot的一些基础使用方法和敲了一些例子,是时候写一个简单的crud来将之前学的东西做一个整合了 -- 一个员工列表的增删改查. 使用 restful api ...

  5. MQ相关

    1. 如何保证消息按顺序执行 2. 如何保证消息不重复消费 3. 如何保证消息不丢失 4.RabbitMQ Java Client简单生产者.消费者代码示例

  6. git下,输入git log 进入log 怎么退出

    解决方案: 英文状态下按Q就可以了 ctrl + c (应该是Linux命令中断的意思,很多中断都是这个命令). Paste_Image.png

  7. Ajax + PHP 的用法以及遇见的问题

    由于自己是个php小白,所以新知识点都要自己去不断的试验和摸索. 分享下自己用php + ajax交互的用法和问题. 前端代码: $.ajax({ type: "POST", da ...

  8. vi / vim 基本操作

    进入vi的命令         vi filename :打开或新建文件,并将光标置于第一行首    vi n filename :打开文件,并将光标置于第n行首    vi filename :打开 ...

  9. Java 进阶面试问题必备

    面向对象编程的基本理念与核心设计思想 解释下多态性(polymorphism),封装性(encapsulation),内聚(cohesion)以及耦合(coupling). 继承(Inheritanc ...

  10. Analysis of Autherntication Protocol with Scyther :Case Study ---补充整理

    1.Needham-Schroeder public Key Protocol (基于非对称的加密协议) the Protocol's authors are Roger NeedHam and Mi ...