可变参数列表是通过stdarg.h内的宏来实现的:

类型 va_list

三个宏:

  va_start

  va_arg

  va_end

我们可以声明一个va_list变量,与这三个宏配合使用。

可变参数必须要有一个命名参数,因为可变参数是通过栈来实现的,函数中的最右边的参数最先入栈。

void function(int a, int b, int c)
{
int d;
...
}

其栈结构为

0x1ffc-->d

0x2000-->a

0x2004-->b

0x2008-->c

栈的空间是连续的,所以函数第一个必须是命名参数,这样就可以通过第一个参数来寻址,根据类型所占字节偏移,获取后续的所有可变参数值。

下面是利用可变参数计算平均值函数:

#include <stdarg.h>

float average(int n_num, ...)
{
int count;
float sum = 0; //var_arg是一个指针,通过va_start指向第一个命名参数位置
va_list var_arg;
va_start(var_arg, n_num); for (count = 0; count < n_num; count++) {
//va_arg第二个参数是类型,根据类型来偏移获取参数值
sum += va_arg(var_arg, int);
} //让指针指向NULL,不在指向堆栈
va_end(var_arg); return sum / n_num;
}

所以这些宏存在两个问题,一来无法确定参数数量,因为不同类型所占空间不同,二来无法确定类型,printf函数的类型是通过字符串中的格式字符串来提取类型实现的。

参考:http://blog.chinaunix.net/uid-20545038-id-1648593.html

     http://www.cnblogs.com/cpoint/p/3368993.html

C和指针 第七章 可变参数的更多相关文章

  1. C和指针 第七章 习题

    7.1 hermite递归函数 int hermite(int n, int x) { if (n <= 0) { return 1; } if (n == 1) { return 2 * x; ...

  2. C和指针第七章第五题

    实现一个简化的printf函数,能够处理%d,%f,%s,%c等格式. /*************************************************************** ...

  3. C和指针 第七章 函数递归与迭代

    C语言通过运行时堆栈支持递归函数的实现,递归函数时直接或者间接调用自身的函数,经常有人拿斐波那契实现当做递归的实现,然后这样做效率并不高. n < 1;  Fib(1) =1 n = 2;  F ...

  4. 【转载】va_list 可变参数 简介 va_copy vprintf

    [说明]本文转载自 smart 的文章 http://blog.sina.com.cn/s/blog_590be5290100qhxr.html  及百度百科 va_list是一个宏,由va_star ...

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

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

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

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

  7. 可变参数以及stdcall

    void event_warnx(const char *fmt, ...) EV_CHECK_FMT(1,2); #define EV_CHECK_FMT(a,b) __attribute__((f ...

  8. C++逆向 可变参数Hook

    目录 C++逆向 可变参数Hook 0x00 前言: 0x01 C++可变参数: 可变参数简介 可变参数代码实战 0x02 逆向分析C++可变参数原理 0x03 printf Hook实战 Pwn菜鸡 ...

  9. C和指针 (pointers on C)——第七章:函数(上)

    第七章 函数 这一章对于有一定C的基础的人有一定优秀代码风格的人来说,并非非常虐.关于stdarg宏可能有些陌生.它负责可变參数列表的定义. 总结: 新式风格和旧式风格就不要提了.八百年前的事情. 函 ...

随机推荐

  1. 第37课 深度解析QMap与QHash

    1. QMap深度解析 (1)QMap是一个以升序键顺序存储键值对的数据结构 ①QMap原型为 class QMap<K, T>模板 ②QMap中的键值对根据Key进行了排序 ③QMap中 ...

  2. BZOJ1002[FJOI2007]轮状病毒

    Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子 和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下 ...

  3. c#获取下载路径

    Request.ApplicationPath  返回/或者iis下目录.如果个人网站是在iis网站下面新建的目录aaa,返回如:/aaa Request.Url.Authority  返回域名和端口 ...

  4. node基础13:异步流程控制

    1.流程控制 因为在node中大部分的api都是异步的,比如说读取文件,如果采用回调函数的形式,很容易造成地狱回调,代码非常不容易进行维护. 因此,为了解决这个问题,有大神写了async这个中间件.极 ...

  5. 简单CSS3实现炫酷读者墙

    如题,给大家介绍和讲解几个常用的CSS3属性,并用到实处. 先看demo(请使用Chrome或者Firefox浏览,IE的靠边): 点此查看实例 觉得爽的可以继续阅读下面的知识点,感觉不爽的可绕行. ...

  6. shell脚本每天自动备份mysql数据库

    一.mysql提供了一个mysqldump的工具可以方便的导出导入数据库信息: 二.使用命令行shell测试执行mysqldump,理解必备的参数,查看生成的sql备份文件是否符合需求: /usr/b ...

  7. 如何重复使用IEnumerable对象来枚举?

    我在2011年9月发表了一个问问,http://q.cnblogs.com/q/28679/. 没人理我. 自己看了一下,尝试自己解决: 原问题: MSDN: 在非泛型集合中,您可以在调用 Reset ...

  8. jquery-抖动图组轮播动画

    JQ匀速抖动图组轮播动画 一.HTML+CSS <!DOCTYPE html> <html lang="en" xmlns="http://www.w3 ...

  9. Xcode调试技巧(断点和重构)

    首先是最简单的普通断点有时候不知道是那个方法调用的崩溃的这个方法,传了个奇怪的值,打个断点就就可以在左侧工具栏里看到最近几个方法执行的循序,和那个方法调用的本方法,一般小问题在这里就可以解决啦~ 条件 ...

  10. Lua和C++交互详细总结

    转自:http://cn.cocos2d-x.org/tutorial/show?id=1474 一.Lua堆栈 要理解Lua和C++交互,首先要理解Lua堆栈. 简单来说,Lua和C/C++语言通信 ...