快捷搜索:

用C语言实现参数个数可变的函数

采纳C说话编程的时刻,函数中形式参数的数目平日是确定的,在调用时要依次给出与形式参数对应的所有实际参数。但在某些环境下盼望函数的参数个数可以根据必要确定。范例的例子有大年夜家认识的函数printf()、scanf()和系统调用execl()等。那么它们是如何实现的呢?

C编译器平日供给了一系列处置惩罚这种环境的宏,以樊篱不合的硬件平台造成的差异,增添法度榜样的可移植性。这些宏包括va—start、va—arg和va—end等。

应用这些宏有两种不合的形式,二者在法度榜样中包括的头文件不合,宏的定义也存在一些区别。这两种要领对应的头文件和宏的声明见表1。

采纳ANSI标准形式时,参数个数可变的函数的原型声明是:

type funcname(type para1, type para2, ...)

这种形式至少必要一个通俗的形式参数,后面的省略号不表示省略,而是函数原型的一部分,type是函数返回值和形式参数的类型。

采纳与UNIX System V兼容的声明要领时,参数个数可变的函数原型是:

type funcname(va—alist)

va—dcl

这种形式不必要供给任何通俗的形式参数,type是函数返回值的类型。va—dcl是对函数原型声明中参数va—alist的具体声明,实际是一个宏定义,对不合的硬件平台采纳不合的类型来定义,但在着末都包括了一个分号,是以va—dcl后不再必要加上分号了。va—dcl在代码中必须原样给出,va—alist在VC中可以原样给出,也可以略去,但在UNIX上的CC或Linux上的GCC中都要省略掉落。此外,采纳头文件stdarg.h编写的法度榜样是相符ANSI标准的,可以在各类操作系统和硬件上运行,而采纳头文件varargs.h的要领仅仅是为了与曩昔的法度榜样兼容。以是建议大年夜家应用前者。两种要领的基滥觞基本理是同等的,只是在语法形式上有一些细微的差别。以下主要就前一种要领对参数的处置惩罚做出阐明。

va—start使argp指向第一个可选参数。va—arg返回参数列表中确当前参数并使argp指向参数列表中的下一个参数。va—end把argp指针清为NULL。函数体内可以多次遍历这些参数,然则都必须以va—start开始,并以va—end结尾。

调用者在实际调用参数个数可变的函数时,要经由过程必然的措施指明实际参数的个数,例如把着末一个参数置为空字符串(系统调用execl()便是这样的)、-1或其他的要领。

下面给出一个详细的例子,前一部分是采纳了相符ANSI标准形式的代码,后一部分是采纳了与UNIX System V兼容要领的代码。代码中加了一些注释,这里就不再说清楚明了。该例子已经在VC/Windows NT4.0、CC/AIX4.3.2.0、GCC/Redhat Linux 6.0情况下编译并正常运行。

1.演示若何应用参数个数可变的函数,采纳ANSI标准形式

#include 〈stdio.h〉

#include 〈string.h〉

#include 〈stdarg.h〉

/? 函数原型声明,至少必要一个确定的参数,留意括号内的省略号 ?/

int demo( char ?, ... );

void main( void )

{

demo(″DEMO″, ″This″, ″is″, ″a″, ″demo!″, ″″);

}

/? ANSI标准形式的声明要领,括号内的省略号表示可选参数 ?/

int demo( char ?msg, ... )

{

va—list argp;

/? 定义保存函数参数的布局 ?/

int argno = 0; /? 记载参数个数 ?/

char ?para;

/? 寄放掏出的字符串参数 ?/

/? argp指向传入的第一个可选参数,msg是着末一个确定的参数 ?/

va—start( argp, msg );

while (1) {

para = va—arg( argp, char ?);

/? 掏出当前的参数,类型为char ?. ?/

if ( strcmp( para, ″″) == 0 )

/? 采纳空串唆使参数输入停止 ?/

break;

printf(″Parameter #%d is: %s\n″, argno, para);

argno++;

}

va_end( argp ); /? 将argp置为NULL ?/

return 0;

}

您可能还会对下面的文章感兴趣: