C语言可变长參数实现原理
微博:http://weibo.com/u/2203007022
(1) C语言可变參数
我们能够从C语言的printf得出可变參数的作用。printf函数的原型例如以下:
int printf ( const char * format, ... );
通过使用可变个数參数,就是传入的參数个数是可变的,如printf须要依据format实參传入多个实參。
(2) C语言可变參数的使用
以下一个函数myprintf是自己实现的比較简单的printf函数。不完整可是能够说明可变參数的使用方法。
/*
* Author: guojun07
*/ #include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h> void myprintf(char *format, ...) {
va_list ap;
int pos = 0;
int int_val = 0;
float f_val;
char buf[64];
memset(buf, 0, 64);
// 得到全部的參数放到下一个list中ap中
va_start(ap, format);
while (format[pos] != '\0') {
// 推断'%'。表示要得到下一个參数
if (format[pos] == '%') {
pos ++;
switch(format[pos]) {
case 'd':
case 'u':
// 得到ap中的下一个參数
int_val = va_arg(ap, int);
sprintf(buf, "%d", int_val);
// 将数据写到标准输出
write(STDOUT_FILENO, buf, strlen(buf));
memset(buf, 0, 64);
pos ++;
break;
case 'f':
// 得到ap中的下一个參数
f_val = (float)va_arg(ap, double);
sprintf(buf, "%f", f_val);
// 将数据写到标准输出
write(STDOUT_FILENO, buf, strlen(buf));
memset(buf, 0, 64);
pos ++;
break;
default:
break;
}
} else {
write(STDOUT_FILENO, &(format[pos]), 1);
pos ++;
}
}
} int main(void){
myprintf("this is a testing, i = %d, u = %u, f = %f\n", -1, 5, 0.2);
return 0;
}
程序的数据结果例如以下:
guojun8@guojun8-desktop:~/test/valist$ ./main
this is a testing, i = -1, u = 5, f = 0.200000
(3) 实现
以下介绍C语言可变长度參数的实现。事实上现与一个数据结构(va_list)和三个宏(va_start, va_end, va_arg)相关,从源代码中能够看到这些实现以下的来自linux内核源代码中的文件(include/acpi/platform/acenv.h)
#ifndef _VALIST
#define _VALIST
typedef char *va_list;
#endif /* _VALIST */
/*
* Storage alignment properties
*/
#define _AUPBND (sizeof (acpi_native_int) - 1)
#define _ADNBND (sizeof (acpi_native_int) - 1)
/*
* Variable argument list macro definitions
*/
#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd)))
#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))
#define va_end(ap) (void) 0
#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
a) va_list
从实现中能够看出va_list类型实际上就是一个指针。
b) va_start
这个宏的作用是将T所指向的參数后面的内容放到ap中。当中_bnd (A,_AUPBND)是返回A的size并与系统的机器位数对齐。由于參数在栈中的地址一定是与系统的字长对齐的,当中acpi_native_int就表示机器字长。
c) va_end
这个宏的作用就是返回0。
d) va_arg
这个宏的作用是取得ap指向的当前的參数,并将ap指向參数列表中的下一个參数。
C语言可变长參数实现原理的更多相关文章
- C语言变长參数的认识以及宏实现
1.认识 变长參数是C语言的特殊參数形式.比如例如以下函数声明: int printf(const char *format, ....); 如此的声明表明,printf函数除了第一个參数类型为con ...
- Java 变长參数Varargs
Varargs (variable arguments)可变长參数是Java 1.5引入的特性. 方法的形參如print(String ... s),实參为随意数目的值. public class V ...
- java 变长參数使用原则
1.java变长參数用...表示,如Print(String... args){ ... }; 2.假设一个调用既匹配一个固定參数方法.又匹配一个变长參数方法,则优先匹配固定參数的方法 3.假设一个 ...
- C++11 新特性之 变长參数模板
template <typename ... ARGS> void fun(ARGS ... args) 首先明白几个概念 1,模板參数包(template parameter pack) ...
- C语言函数參数传递原理
C语言中參数的传递方式一般存在两种方式:一种是通过栈的形式传递.还有一种是通过寄存器的方式传递的. 这次.我们仅仅是具体描写叙述一下第一种參数传递方式,第二种方式在这里不做具体介绍. 首先,我们看一下 ...
- linux kernel的cmdline參数解析原理分析
利用工作之便,今天研究了kernel下cmdline參数解析过程.记录在此.与大家共享.转载请注明出处.谢谢. Kernel 版本:3.4.55 Kernel启动时会解析cmdline,然后依据这些參 ...
- [转]深度探索C语言函数可变长参数
转自:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html 一.基础部分 1.1 什么是可变长参数 可变长参数:顾名 ...
- object-c 不定參数的遍历和原理
object-c接收随意类型的參数: /** * 接收String类型的多个參数 * @param firsParam 第一个參数 */ -(void)TestString:(NSString*)fi ...
- Effective JavaScript Item 22 使用arguments来创建接受可变參数列表的函数
本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变參数列表函数average,它实际上仅仅声明了一个数组作为參数,可是利用apply ...
随机推荐
- [译]移动API安全终极指南
文章主要讲了移动api调用的授权和验证问题,原文链接:The Ultimate Guide to Mobile API Security 移动API的使用是Stack Overflow和 Stormp ...
- 入门到熟练-SpringBoot
Spring Boot概述 1.1. Spring Boot是什么 Spring Boot是一套基于Spring框架的微服务框架. 1.2. Spring Boot框架出现的背景 由于Spring是一 ...
- tomcat配置虚拟路径保存、访问图片
一些项目中往往需要上传一些图片文件之类,一般不建议直接保存在数据库内,往往是讲图片等资源保存在服务器的某个文件夹下,传统做法是上传到部署目录下,通过相对路径进行访问.这样当我们系统需要进行升级,进行全 ...
- MyBatis学习笔记1--初识MyBatis
我也是初学者,写博客只是想把自己的整个思路整理一下,有不对或者不好的地方,请大家多多指正. 1.MyBatis简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射. ...
- Python——网络爬虫
此篇文章继续跟着小甲鱼的视频来初学网络爬虫,除了小甲鱼的网站上可下载视频,发现b站上也有全套的视频哦,会比下载来的更方便些. 网络爬虫,又称为网页蜘蛛(WebSpider),非常形象的一个名字.如果你 ...
- 很考验人的java内存加载面试题
源代码如下,求结果 public class MemoryAnalyse { public static int k = 0; public static MemoryAnalyse t1 = new ...
- SSM 配合 Mysql 数据库和代码数据源主从分离
大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...
- mysql多个TimeStamp设置(转)
原文地址:http://www.cnblogs.com/yjf512/archive/2012/11/02/2751058.html timestamp设置默认值是Default CURRENT_TI ...
- 开源项目 easydownload
一个用于下载的 android library库, 源码 支持多线程断点下载, 支持消息通知. 支持优先级下载. 支持暂停,继续,删除下载列表 支持多服务器下载. 使用方式 compile 'co ...
- 翻译连载 | 附录 A:Transducing(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...