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 ...
随机推荐
- Cocoapods使用过程中遇到的问题
前言:记录一些在CocoaPods使用过程中遇到的问题,本地环境:Xcode9.0 发现有的时候在执行pod init的时候不能正常地创建出来pod File文件,显示的错误如下: ――― MARKD ...
- 小米/红米导入VCF联系人乱码问题解决
PS:尽量不要用什么豌豆荚啊.微信啊.QQ啊之类的通讯录备份,那就等于把自己的通讯录免费送给腾讯他们了....还是自己手动的好一些,但是小白用户或者经常丢手机的卖就卖吧,总比联系人都丢了要好~~~ 默 ...
- java实现网络爬虫
import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.r ...
- VMware14.0.0 版本虚拟机安装Ubuntu16.04 LTS版本Linux系统(多图详细步骤)
一.前期准备工作 1.成功安装完成VMware14软件: 2.去Ubuntu官网下载Ubuntu16.0.4 LTS 版本的镜像文件. 二.安装步骤 1.打开VMware软件,选择<创建虚拟机& ...
- [转载] Java NIO教程
转载自并发编程网 – ifeve.com http://ifeve.com/java-nio-all/ 关于通道(Channels).缓冲区(Buffers).选择器(Selectors)的故事. 从 ...
- Python之matplotlib学习(一)
小试牛刀 在上一节已经安装好matplotlib模块,下面使用几个例子熟悉一下. 对应的一些文档说明: http://matplotlib.org/1.3.1/api/pyplot_summary.h ...
- js判断手机或Pc端登陆.并跳转到相应的页面
<script src="~/Web/js/jquery-1.10.1.min.js"></script> <script> $(functio ...
- alex python of day2
模块 sys模块:sys模块是用c语言写的,所以在lib下是不会有sys.py这个文件存在 1 import sys 2 print(sys.path) #打印环境变量 3 print(sys.a ...
- LKD: Chapter 6 Kernel Data Structures
这一章我们研究四种主要的数据结构: linked lists, queues, maps, binary trees. Linked Lists:(<linux/list.h>) 在lin ...
- Ani动态光标格式解析
数据结构: Ani文件中的数据是按区段存放的,区段数据结构如下: 标识符(4字节ASCII),数据长度(一个DWORD),数据 按照此规则来看Ani文件,文件起始12字节可以理解为标准文件头,除数据长 ...