1 /*my_stdarg.h*/
 2 /*
 3  * c允许定义可接受一个可变参数列表的函数。而且是自己定义的额外的函数。
 4  * stdarg.h定义的宏。允许在任何时候从头到尾地便利一个附加参数列表。
 5  * 在遇到每一个参数之前,必须知道它的类型,但在一个给定的调用发生之前,不必知道它的细节。
 6  * 宏va_start,一个函数必须至少声明一个固定的参数。宏va_start引用了最后一个固定参数所以它能够对可变参数进行定位,
 7  * 访问所有未命名的参数之前调用宏。对类型va_list ap初始化。
 8  * 宏va_arg,每一次调用都会修改ap,每次调用这个宏展开的表达式的类型和值跟调用的下一个参数的相同。
 9  * 第一次调用返回parmN后面的第一个参数。
10  * 宏va_end,一个函数在返回到它的调用者之前一定要调用va_end。
11  * stdarg.h声明了一种类型,定义了3个宏,这样就可以提前访问一个参数表,调用函数在编译时并不知道这个参数表中参数的数目和类型。
12  * 在...之前的那个参数起着特殊的作用,记作parmN。
13  * 声明类型va_list。
14  * 可重复使用。
15  *
16  *
17  * c标准定义,一个可变参数表在内存中占据了一个连续的字符数组;
18  *         后继的参数占据着字符数组更高为位。
19  *        一个参数占据的空间开始于2^N字节的整数倍的存储边界。
20  *        存储空间的大小是可以表示这个参数2^N字节的最小倍数。
21  *        存储空间留下的任何间隙总是在参数数据对象的开头或者结尾。
22  *
23  */
24
25 #define _AUPBND    3/*在可变参数表内部确定存储边界的屏蔽宏,2^N-1*/
26 #define _ADNBND    3/*确定存储空隙是否在一个参数数据对象的开端或者结尾的屏蔽宏,在尾处2^N-1,否则为0*/
27 /*4倍数对齐,且结尾为开始出,则 3  0*/
28 #ifndef MY_STDARG_H_
29 #define MY_STDARG_H_
30 /*保存一个指向下一个参数空间的起始位置的指针*/
31 typedef char *va_list;
32 /*
33  * 通过增加va_list对象ap的内容来使它指向下一个参数空间的起始位置,然后再退回来指向当前参数的起始位置,
34  * 然后通过强制类型转换把这个指针值转换成为指定类型的指针,最后解引用这个指针以访问存储在数据对象中的值。
35  */
36 #define va_arg(ap, T) (*(T *)(((ap) += _Bnd(T, _AUPBND)) - _Bnd(T, _ADNBND)))
37 /*占位符*/
38 #define va_end(ap) (void)0
39 /*跳过已命名的参数,也就是最后一个固定参数,使用内部宏_Bnd把它的参数大小操作为2^N字节的一个倍数*/
40 #define va_start(ap, A) (void)((ap) = (char *)&(A) + _Bnd(A, _AUPBND))
41 #define _Bnd(X, bnd) (sizeof(X) + (bnd) &~ (bnd))
42 #endif

 1 /*my_stdarg.c*/
 2 #include <assert.h>
 3 #include <stdio.h>
 4 #include "my_stdarg.h"
 5
 6 typedef struct {
 7     char c;
 8 }cstruct;
 9
10 static int tryit(const char *fmt, ...)
11 {
12     int ctr = 0;
13     va_list ap;
14
15     va_start(ap, fmt);
16     for(; *fmt; ++fmt)
17         switch(*fmt){
18             case 'i':
19                 assert(va_arg(ap, int) == ++ctr);
20                 break;
21             case 'd':
22                 assert(va_arg(ap, double) == ++ctr);
23                 break;
24             case 'p':
25                 assert(va_arg(ap, char *)[0] == ++ctr);
26                 break;
27             case 's':
28                 assert(va_arg(ap, cstruct).c == ++ctr);
29         }
30         va_end(ap);
31         return ctr;
32 }
33 int main(void)
34 {
35     cstruct x = {3};
36
37     assert(tryit("iisdi", '\1', 2, x, 4.0, 5) == 5);
38     assert(tryit("") == 0);
39     assert(tryit("pdp", "\1", 2.0, "\3") == 3);
40     printf("sizeof(va_list) == %u\n", sizeof(va_list));
41     puts("success testing stdary.h");
42     return 0;
43 }

转载于:https://www.cnblogs.com/kevin-kang/p/3172720.html

stdarg.h(c标准库)相关推荐

  1. setjmp.h(c标准库)

    主要看了思路,代码未测试. 1 /*yvals.h*/ 2 #define _YVALS_H_ 3 4 #define MYEDOM 33 5 #define MYERANGE 34 6 #defin ...

  2. ctype.h(c标准库)

    1 /*my_ctype.h*/ 2 #ifndef _MY_CTYPE_H_ 3 #define _MY_CTYPE_H_ 4 5 /* 6 * 字符类别 7 * 数字,0-9之间的十进制数:十六进 ...

  3. C 标准库 —— limits.h

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

  4. C 标准库 —— stdio.h

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

  5. C 标准库 —— time.h

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

  6. C 标准库—— string.h

    C 标准库 -- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand ...

  7. C 标准库—— stdlib.h(包括 rand srand 的实现)

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

  8. C 标准库——cmath/math.h

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

  9. C 标准库—— assert.h

    C 标准库-- string.h C 标准库 -- time.h C 标准库 -- limits.h C 标准库 -- stdio.h C 标准库-- stdlib.h(包括 rand srand 的 ...

最新文章

  1. 【javascript】深入理解对象
  2. 0.0.5、Linux命令
  3. mysql日志监控 zabbix_zabbix 监控mysql日志
  4. c#.net全站防止SQL注入类的代码
  5. 使用Go实现Socket服务端和客户端通信
  6. k8s 部署spring cloud项目
  7. ISA防火墙基础及应用
  8. pycharm菜单栏不见了被隐藏了,两种处理方法
  9. 【2016阿里安全峰会】“安全攻防”烧脑博弈全解读【附PDF下载】
  10. Android Unable to delete file: build\intermediates\manifests\full\debug\AndroidManifest.xm
  11. 【渝粤题库】陕西师范大学202021宏观经济学作业(高起本、专升本)
  12. 解决银河麒麟系统开机后桌面无图标,只有下方开始菜单和任务栏可操作问题
  13. 网易云音乐面向用户增长的数据治理实践
  14. Java实现CSV文件的读写
  15. c语言二级考试试卷,二级 C语言考试试卷
  16. WPS文字转Word用什么软件
  17. 经纬恒润智能驾驶创新之路
  18. 昆明理工大学知道计算机答案,昆明理工大学 计算机基础教材参考答案(1-6章)
  19. 微信公众号开发之语音消息识别
  20. play商店 小米_Google Play 商店

热门文章

  1. 交换两个数不引入第三个变量
  2. C语言经典例24-分数累加和
  3. 【计算机网络】数据链路层 : 概述 ( 基本概念 | 功能 | 为 “网络层“ 提供的服务 )
  4. 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 缓存策略 | LruCache 内存缓存 | LruCache 常用操作 | 工具类代码 )
  5. 【Kotlin】Kotlin 语言集合中的高阶函数详解 ( 数据类 data class | maxBy | minBy | filter | map | any | count | find )
  6. Redis 你该懂的点
  7. git push error. ! [rejected] master - master (non-fast-forward)
  8. python中关于input和raw_input的使用方法
  9. 2.对于所有对象都通用的方法_EJ
  10. Centos环境docker的正确安装及疑难杂症