`
andyliuxs
  • 浏览: 139407 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

C语言深入浅出可变参数函数的使用技巧

阅读更多

深入浅出可变参数函数的使用技巧本文主要介绍可变参数的函数使用,然后分析它的原理,程序员自己如何对它们实
现和封装,最后是可能会出现的问题和避免措施。

VA函数(variable argument function),参数个数可变函数,又称可变参数函数
。C/C++编程中,系统提供给编程人员的va函数很少。*printf()/*scanf()系列函数
,用于输入输出时格式化字符串;exec*()系列函数,用于在程序中执行外部文件(
main(int argc,char*argv[]算不算呢,与其说main()也是一个可变参数函数,倒不
如说它是exec*()经过封装后的具备特殊功能和意义的函数,至少在原理这一级上有
很多相似之处)。由于参数个数的不确定,使va函数具有很大的灵活性,易用性,对
没有使用过可变参数函数的编程人员很有诱惑力;那么,该如何编写自己的va函数
,va函数的运用时机、编译实现又是如何。作者借本文谈谈自己关于va函数的一些
浅见。

一、 从printf()开始

从大家都很熟悉的格式化字符串函数开始介绍可变参数函数。

原型:int printf(const char * format, ...);

参数format表示如何来格式字符串的指令,…

表示可选参数,调用时传递给"..."的参数可有可无,根据实际情况而定。

系统提供了vprintf系列格式化字符串的函数,用于编程人员封装自己的I/O函数。


int vprintf / vscanf(const char * format, va_list ap); // 从标准输入/输出
格式化字符串

int vfprintf / vfsacanf(FILE * stream, const char * format, va_list ap);
// 从文件流

int vsprintf / vsscanf(char * s, const char * format, va_list ap); // 从
字符串

// 例1:格式化到一个文件流,可用于日志文件

FILE *logfile;

int WriteLog(const char * format, ...)

{

va_list arg_ptr;

va_start(arg_ptr, format);

int nWrittenBytes = vfprintf(logfile, format, arg_ptr);

va_end(arg_ptr);

return nWrittenBytes;

}

// 调用时,与使用printf()没有区别。

WriteLog("%04d-%02d-%02d %02d:%02d:%02d  %s/%04d logged out.",

nYear, nMonth, nDay, nHour, nMinute, szUserName, nUserID);

 

同理,也可以从文件中执行格式化输入;或者对标准输入输出,字符串执行格式化

在上面的例1中,WriteLog()函数可以接受参数个数可变的输入,本质上,它的实现
需要vprintf()的支持。如何真正实现属于自己的可变参数函数,包括控制每一个传
入的可选参数。

二、 va函数的定义和va宏

C语言支持va函数,作为C语言的扩展--C++同样支持va函数,但在C++中并不推荐使
用,C++引入的多态性同样可以实现参数个数可变的函数。不过,C++的重载功能毕
竟只能是有限多个可以预见的参数个数。比较而言,C中的va函数则可以定义无穷多
个相当于C++的重载函数,这方面C++是无能为力的。va函数的优势表现在使用的方
便性和易用性上,可以使代码更简洁。C编译器为了统一在不同的硬件架构、硬件平
台上的实现,和增加代码的可移植性,提供了一系列宏来屏蔽硬件环境不同带来的
差异。

ANSI C标准下,va的宏定义在stdarg.h中,它们有:va_list,va_start(),va_ar
g(),va_end()。

// 例2:求任意个自然数的平方和:

int SqSum(int n1, ...)

{

va_list arg_ptr;

int nSqSum = 0, n = n1;

va_start(arg_ptr, n1);

while (n > 0)

{

    nSqSum += (n * n);

    n = va_arg(arg_ptr, int);

}

va_end(arg_ptr);

return nSqSum;

}

// 调用时

int nSqSum = SqSum(7, 2, 7, 11, -1);

 

可变参数函数的原型声明格式为:

type VAFunction(type arg1, type arg2, … );

参数可以分为两部分:个数确定的固定参数和个数可变的可选参数。函数至少需要
一个固定参数,固定参数的声明和普通函数一样;可选参数由于个数不确定,声明
时用"…"表示。固定参数和可选参数公同构成一个函数的参数列表。

借助上面这个简单的例2,来看看各个va_xxx的作用。

va_list arg_ptr:定义一个指向个数可变的参数列表指针;

va_start(arg_ptr, argN):使参数列表指针arg_ptr指向函数参数列表中的第一个
可选参数,说明:argN是位于第一个可选参数之前的固定参数,(或者说,最后一
个固定参数;…之前的一个参数),函数参数列表中参数在内存中的顺序与函数声
明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, c
har c, …),则它的固定参数依次是a,b,c,最后一个固定参数argN为c,因此就是
va_start(arg_ptr, c)。

va_arg(arg_ptr, type):返回参数列表中指针arg_ptr所指的参数,返回类型为ty
pe,并使指针arg_ptr指向参数列表中下一个参数。

va_copy(dest, src):dest,src的类型都是va_list,va_copy()用于复制参数列表
指针,将dest初始化为src。

va_end(arg_ptr):清空参数列表,并置参数指针arg_ptr无效。说明:指针arg_pt
r被置无效后,可以通过调用va_start()、va_copy()恢复arg_ptr。每次调用va_st
art() / va_copy()后,必须得有相应的va_end()与之匹配。参数指针可以在参数列
表中随意地来回移动,但必须在va_start() … va_end()之内

 

分享到:
评论

相关推荐

    《C语言函数参考手册》

    综上所述,《C语言函数参考手册》是一本深入浅出的C语言函数指南,它以详尽的函数介绍和丰富的实例,帮助开发者巩固基础,提高编程效率,是学习和工作中的一大助力。无论你是初学者还是经验丰富的程序员,这本书都能...

    深入浅出.MFC

    《深入浅出MFC》是一本专为C++程序员深入理解Microsoft Foundation Classes (MFC)框架而编写的经典书籍。MFC是微软公司为Windows平台开发应用程序提供的一种强大的类库,它基于C++,极大地简化了Windows API的使用,...

    C语言函数手册 适合C的初学者

    本手册《C语言函数手册》将深入浅出地介绍C语言中的各种函数,旨在为学习者提供有力的支持。 在C语言中,函数是一组相关的语句,它们执行特定任务并可能接受输入参数(也称为参数或形式参数),并返回一个值(如果...

    C语言程序设计(第三版)

    这本书深入浅出地介绍了C语言的基础知识、编程技巧和实践应用,是学习C语言的重要参考资料。标签“C语言”明确了本书的核心主题,即针对C语言的学习和研究。 在C语言程序设计中,有几个关键的知识点值得我们深入...

    浅谈C语言函数的递归调用.pdf

    在编程领域,递归是一种...对于学习C语言的学生和开发者而言,递归函数的深入理解将有助于提升编程技巧,设计出更加优雅高效的算法。同时,我们也应当警惕递归的潜在风险,避免无终止的递归调用和不必要的性能损耗。

    谭浩强C语言电子版_C语言入门首选

    本书以其深入浅出的讲解方式和丰富的实例,使得C语言的学习变得生动有趣。 C语言是一种广泛应用的计算机编程语言,由Dennis Ritchie在20世纪70年代开发,因其高效、灵活和强大的系统编程能力而闻名。它是许多现代...

    水滴石穿C语言之内存使用.pdf

    ### 水滴石穿C语言之内存使用 #### 知识点概览 ...综上所述,文档通过具体的例子深入浅出地介绍了C语言中内存管理的重要性和一些最佳实践。通过理解这些知识点,可以帮助开发者更好地编写出健壮和高效的C程序。

    浅析C语言printf函数的功能及使用.pdf

    本文将深入浅出地探讨`printf`函数的基本功能、参数使用以及常见的格式化控制。 首先,`printf`函数的基本语法如下: ```c int printf(const char *format, ...); ``` 这里的`format`参数是一个字符串,其中包含...

    谭浩强C语言exe电子书

    本书通过深入浅出的方式,系统地向读者展示了C语言的基础知识和编程技巧。从简单的变量声明到复杂的函数设计,从基础的数组操作到灵活的指针应用,谭浩强教授都一一进行了详尽的解说。尤其值得注意的是,在教授基本...

    深入浅出gstreamer开发

    GObject允许实现封装、继承和多态等面向对象的特性,并且对C语言的this指针和vtable(虚函数表)有深入的模拟。理解GObject对象模型对深入学习Gstreamer是非常有帮助的。 在Gstreamer的管道化多媒体框架中,主要的...

    C语言中文网Python教程

    “7.3Python函数参数传递机制(超级详细).html”详细解释了Python的参数传递方式,Python采用“引用传递”的表象,实际上是按对象复制,区分了可变对象和不可变对象的传递行为。 综上所述,这个压缩包提供的教程...

    谭浩强c语言 电子版

    本书不惜笔墨,深入浅出地讲解了指针的概念、指针与数组的关系、指针与函数的关系以及指针与字符串的操作,使读者能够在掌握指针的同时,更深刻地理解C语言内存管理和数据操作的原理。 在C语言中,数组和字符串处理...

    C语言ppt完整版 C语言 ppt

    本C语言PPT完整版将深入浅出地讲解这些内容,结合实例解析,助你在实践中巩固理论知识,掌握C语言的精髓。无论是初学者还是有一定经验的程序员,都能从中受益。通过学习和实践,你将能够编写出高效、可靠的C语言程序...

    浅谈C语言基础:入门与实践

    本文将深入浅出地探讨C语言的基础知识,帮助初学者快速入门并实践。 一、C语言简介 C语言由Dennis Ritchie在1972年开发,作为UNIX操作系统的一部分。它具有强大的数据处理能力和高效的程序执行效率,被视作现代编程...

    《C语言程序设计教程》源代码

    这本书深入浅出地介绍了C语言的基础概念、语法结构和编程技巧,为读者构建了坚实的C语言编程基础。配合源代码学习,可以更直观地理解编程实践中的各种概念,有助于提高编程技能。 在C语言的学习中,有几个关键知识...

    谭浩强C语言word版

    谭浩强教授的这本著作深入浅出地讲解了C语言的基本语法、控制结构、函数、指针、内存管理等核心概念,是学习C语言的经典参考资料。 1. **C语言基础知识**:C语言是一种结构化编程语言,其程序由函数构成,每个函数...

    C语言程序设计第3版(何钦铭,颜晖主编)全套课件

    何钦铭和颜晖主编的第三版教材,以其深入浅出的讲解方式和丰富的实例,深受广大师生喜爱。这套课件是基于教材内容制作的,不仅包含了书中的知识点,还结合了课堂教学的实际需求进行了优化,对于教学和自学C语言来说...

    C语言深层探索+ARM linux移植

    6. **C/C++语言可变参数表深层探索**:可变参数列表允许函数接收不同数量的参数,如printf函数。掌握这种技术可以实现更强大的函数接口。 7. **基于ARM的嵌入式Linux移植真实体验**:移植Linux到ARM平台涉及...

    《C语言程序设计(C99版)》课件PPT

    《C语言程序设计(C99版)》课件PPT是一部深入浅出的教程资源,专为初学者和有一定基础的程序员提供全面的C语言学习指导。C语言是一种广泛应用于系统编程、软件开发、嵌入式系统等领域的高级编程语言,因其高效、灵活...

Global site tag (gtag.js) - Google Analytics