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 ...
随机推荐
- Python爬虫入门:Urllib库的高级使用
1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. 首先,打开我们的浏览 ...
- linux-cp
cp 更改时间: 2017-10-26 - 21:00:54 cp:用来复制文件或者目录的命令,当源文件与目标文件名字相同的时候,当cp 没有参数,源文件会覆盖目标文件 参数 -p:保留源文件或者目录 ...
- ldap数据库--ODSEE--schema
ldap服务器包含上百个对象类型(object class)和属性,这些对象类和属性都可以满足大部分需求,如果你想定义自己的schema,你只能继承扩展现有的schema进行操作. tip: 增加的新 ...
- windows服务启动有界面的程序
大家写windows服务守护进程的时候,肯定会遇到启动的程序看不到界面,只能在任务管理器里面看到xxx.exe问题. 发现可能有如下情况 a.无论是开机,还是程序被关掉后,守护服务启动的程序只能看到任 ...
- Python基础---python中的异常处理
Python中的异常处理 一.什么是异常处理 python解释器检测到错误,触发异常(也允许程序员自己触发异常) 程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关) ...
- python基础(一)------Python基础语法与介绍
编程语言的历史和Python开发 一.编程语言 1.编程语言也是"语言"与英语,汉语等类似,掌握其语法结构,灵活 的运用其语法规则为之重要. 编程语言实现的是程序 ...
- 5)C语言函数(C自考学习)
函数的概念 在一个程序中,如果在不同地点多次执行某项操作,就可以把完成这项操作的程序段从程序中独立出来,定义成函数,而原来程序中凡需要进行这个操作的程序段可以只用"函数调用"来替代 ...
- TensorFlow简易学习[3]:实现神经网络
TensorFlow本身是分布式机器学习框架,所以是基于深度学习的,前一篇TensorFlow简易学习[2]:实现线性回归对只一般算法的举例只是为说明TensorFlow的广泛性.本文将通过示例Ten ...
- Less的!important关键字
Less的!important关键字 在调用 mixin 时,如果在后面追加 !important 关键字,就可以将 mixin 里面的所有属性都标记为 !important.如,以下Less代码: ...
- azure备份虚拟机
备份 azure虚拟机 提前创建了一个linux虚拟机,位置是chinaeast. 如果我们需要备份的虚拟机分别在中国东部和北部,那么需要在两个位置都创建备份库. 创建库 登录经典门户,新建-> ...