//描述:利用可变参数列表统计一组数的平均值
#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. 5_PHP数组_3_数组处理函数及其应用_1_快速创建数组的函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 一.快速创建数组的函数 1. range() 函数 程序: <?php $numbers = range(1 ...

  2. 【洛谷 P4688】 [Ynoi2016]掉进兔子洞(bitset,莫队)

    题目链接 第一道Ynoi 显然每次询问的答案为三个区间的长度和减去公共数字个数*3. 如果是公共数字种数的话就能用莫队+bitset存每个区间的状态,然后3个区间按位与就行了. 但现在是个数,bits ...

  3. 深入理解JVM(六) -- GC执行原则和方案

    上篇文章中,我们了解了Java虚拟机垃圾回收的思路和策略,这篇文章我们将了解Java是如何实现高效的回收算法的. 我们需要了解,内存回收必须要保证“一致性”,意思就是在执行GC分析的时候,系统看起来要 ...

  4. python3实现unix域协议(tcp、udp)通讯

    socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIXDomain Socket.虽然网络socket也可用于同一台主机的进程间通讯(通过loopb ...

  5. 七分钟理解 Java 的反射 API

    像java一样,一种具有反射功能的语言.允许开发人员在运行时检查类型.方法.字段.注解等,并在程序运行时决定是否使用. 为此,Java的反射API提供类,类,字段,构造函数,方法,注释和其他. 使用它 ...

  6. 尚硅谷韩顺平Linux教程学习笔记

    目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...

  7. javascript_17-基本类型和引用类型

    基本类型 直接存储值 Number . String .Boolean undefined.null 引用类型 存储引用 -Object.Array.Date.函数 包装基本类型--引用类型 func ...

  8. Linux下用的脚本

    http://blog.itpub.net/29510932/viewspace-1166603/ 批量启动Tomcat 点击(此处)折叠或打开 #!/bin/bash #JDK路径 export J ...

  9. Kubernetes 1.15部署日记-使用kubeadm--<5-6>

    5.配置pod网络 5.1下载calico 网络配置文件 [root@k8s-1 libj]# curl -O https://docs.projectcalico.org/v3.6/getting- ...

  10. SQL SERVER-解析Extendevent文件数据

    --解析xel数据 select SWITCHOFFSET(n.value('@timestamp','Datetime'),'+08:00') as EventTime, n.value('(dat ...