C语言可变长参数实现原理
来源:互联网 发布:数据库中各表的结构 编辑:程序博客网 时间:2024/06/09 20:57
(1) C语言可变参数
我们可以从C语言的printf得出可变参数的作用,printf函数的原型如下:int printf ( const char * format, ... );通过使用可变个数参数,就是传入的参数个数是可变的,如printf需要根据format实参传入多个实参。
(2) C语言可变参数的使用
下面一个函数myprintf是自己实现的比较简单的printf函数,不完整但是可以说明可变参数的用法。- /*
- * Author: enough
- */
- #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;
- }
程序的数据结果如下:
enough@enough-desktop:~/test/valist$ ./mainthis 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))))
从实现中可以看出va_list类型实际上就是一个指针;
b) va_start
这个宏的作用是将T所指向的参数后面的内容放到ap中,其中_bnd (A,_AUPBND)是返回A的size并与系统的机器位数对齐,因为参数在栈中的地址一定是与系统的字长对齐的,其中acpi_native_int就表示机器字长;
c) va_end
这个宏的作用就是返回0;
d) va_arg
这个宏的作用是取得ap指向的当前的参数,并将ap指向参数列表中的下一个参数。(转载自:http://blog.chinaunix.net/uid-13991680-id-4234493.html)
0 0
- C语言可变长参数实现原理
- C语言可变长参数实现原理
- C语言可变长参数列表原理与实现
- C语言可变长参数实现“多态”
- C 语言可变参数实现原理
- C语言可变参数函数实现原理
- C语言可变参数函数实现原理
- C语言:va_start、va_end、va_arg 实现可变长参数
- C语言 可变长参数函数的实现
- C语言中的可变长参数(转载)
- C语言中的可变长参数
- C语言中的可变长参数
- C语言——可变长参数
- c语言中的可变长参数
- C语言可变长参数函数
- C语言中可变长参数使用
- C,C++可变长参数实现
- C可变参数实现原理
- Coursera Machine Learning Week 7: support vector machines
- 杂谈:你选择coco 还是unity3d?
- 初识shell 2
- 1Z0-051 QUESTION 4 单行函数Single-Row Functions
- 左耳朵耗子谈云计算:拼的就是运维
- C语言可变长参数实现原理
- PL/SQL远程备份和恢复Oracle数据库
- 转:金庸笔下的良好代码风格
- 《大话设计模式》—— 读后感(8)雷锋依然在人间——工厂方法模式
- C++重载加号运算符实现两个结构体的相加
- 虚函数、纯虚函数
- 嵌入式linux flash分区配置 【转】
- 软件体系结构风格---基于事件的隐式调用
- Oracle 用户管理(二)