可变参数列表源码的剖析
来源:互联网 发布:男人影视软件下载 编辑:程序博客网 时间:2024/05/21 14:16
C语言中的可变参数
1、C语言中的可变参数列表:C语言中有时候会遇到一些参数个数是可变的函数,像scanf,printf等,这些函数内部的参数列表都是可变的。通过将函数实现为可变参数的形式,使得函数可以接受1个以上的任意多个参数。(不固定)
如函数原型:scanf(const char * format,…);
解释:除了format以外,后面跟着的参数 个数,类型是可变的,用…作为一种占位符号。“…”称为可变参数列表,可以用来接受个数和类型不确定的参数。
再例如printf()是一个支持可变参数的函数,可以有多个参数。函数原型:int printf(const char *format,...) 省略号代表参数的个数是不固定的。
(1)可变参数列表在C语言中使用这样的三个宏(va_start,va_arg,va_end)和一个类型(va_list)来进行实现的,他们是定义在stdarg.h头文件中的。
1)va_start原型:
void va_start(va_list ap,paramN);
参数:va_list:存储参数的类型信息
ap:可变参数列表地址
paramN:确定的参数
2)va_arg原型:
void va_arg(va_list ap,type);返回下一个参数的值
3)va_end原型:
void va_end(va_list ap,type);关闭初始化的列表
使用方式:
1) 使用va_list初始化可变参数列表
2) 使用va_arg逐个获取参数值
3)用va_end将可变参数列表清空
例子:
模拟prinf函数的实现:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdarg.h>#include <string.h>#include <stdlib.h>void reverse(char * buf) //将按顺序打印出来的字符串翻转,被myitoa函数调用。{int len = strlen(buf);int i = 0, j = len-1;while (i < j) {char c = buf[i];buf[i] = buf[j];buf[j] = c;i++;j--;}}char *myitoa(int n) //将int型的数字转化为字符串,100(int)->"001",通过reverse函数"001"->"100".{static char buf[100];int i = 0;memset(buf, 0x00, sizeof(buf)); //将buf数组清零do {buf[i++] = (n % 10)+'0';n /= 10;} while (n != 0); reberse(buf);return buf;}void myputs(const char *buf) //打印被myitoa转换好的字符串。{int i;for (i = 0; buf[i] != 0; i++)putchar(buf[i]);}void myprint(char * p,...) //模拟printf函数{va_list str;char* pa;va_start(str, p);int i = 0;for (i = 0; p[i] != 0; i++) {
if (p[i] == '%') {i++;switch (p[i]){case 'd':{int data = va_arg(str, int);myputs(myitoa(data));}break;case 'c':{int c = va_arg(str, char);putchar(c);}break;case 's':{char *s = va_arg(str, char *);for (; *s; s++)putchar(*s);}break;default:break;}}else {putchar(p[i]);}}va_end(str);}int main(){myprint("s=%s %s word! % c %c %c = %d,\n", "s ccc d.\n","hello" ,'b','i','t',100);system("pause");return 0;}
头文件<stdarg.h>提供了
遍历未知数目和类型的函数参数列表的功能。
2、实现可变参数的要点就是想办法取得每个参数的地址,取得地址的办法由以下几个因素决定:
①函数栈的生长方向
②参数的入栈顺序
③CPU的对齐方式
④内存地址的表达方式
3、可变参数的限制 :
- 可变参数必须从头到尾逐个访问。如果你在访问了几个可变参数之后想半途终止,这是可以的,但是,如果你想一开始就访问参数列表中间的参数,那是不行的。
- 参数列表中至少有一个命名参数。如果连一个命名参数都没有,就无法使用va_start。
- 这些宏是无法直接判断实际存在参数的数量。
- 这些宏无法判断每个参数的是类型。
- 如果在va_arg中指定了错误的类型,那么其后果是不可预测的。
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表源码的剖析
- 可变参数列表剖析
- 可变参数列表剖析
- 可变参数列表剖析
- 可变参数列表剖析
- 可变参数列表的源代码剖析
- 可变参数列表源码剖析及实例解析
- 将可变参数列表源码的剖析和你自己的理解写一篇【漂亮】的博客。
- 【C】可变参数列表剖析
- 可变参数列表源码的解析
- 可变参数列表的剖析以及printf函数的实现
- 可变参数列表码的剖析和自己的理解
- Go语言如何实现遗传算法
- dialog第三方框架,material-dialogs的使用
- CULA矩阵相乘和CUBLAS矩阵相乘
- 申请/连接/配置aws linux(redhat)服务器的总结
- 【分布式架构】企业级分布式应用服务EDAS使用攻略(下篇)
- 可变参数列表源码的剖析
- 数据库迁移必备--批量导出定时作业
- Android HTTPS之自签名证书认证(一)
- list与Set、Map区别及适用场景
- zookeeper详解
- 伪代码阅读与学习
- intent用途汇总
- chrome启用跨域正确方法
- Python将被加入高考科目?你怎么看?