oracle 函数可变参数,6.3 带有可变参数的函数

6.3 带有可变参数的函数

在以前的实现中,不能指定函数预期的参数类型,但 ISO C 鼓励您使用原型执行该操作。为支持诸如 printf() 之类的函数,原型语法包括特殊的省略号(…) 终结符。由于一个实现可能需要执行一些特殊操作来处理可变数目的参数,因此 ISO C 要求此类函数的所有声明和定义均包含省略号终结符。

由于参数的 "…" 部分没有名称,因此 stdarg.h 中包含的一组特殊宏为函数提供对这些参数的访问权。此类函数的早期版本必须使用 varargs.h 中包含的类似的宏。

我们假定要编写的函数是一个称为 errmsg() 的错误处理程序,它返回 void,并且函数的唯一固定参数是指定关于错误消息的详细信息的 int。此参数后面可以跟一个文件名和/或一个行号,在它们之后是格式和参数,与指定错误消息文本的 printf() 类似。

为使示例可以使用较早的编译器进行编译,我们广泛使用了仅针对 ISO C 编译系统定义的宏 __STDC__。因此,该函数在相应头文件中的声明为:

#ifdef __STDC__

void errmsg(int code, ...);

#else

void errmsg();

#endif

在包含 errmsg() 定义的文件中,新旧风格变得复杂。首先,要包含的头文件取决于编译系统:

#ifdef __STDC__

#include

#else

#include

#endif

#include

包含 stdio.h 是因为我们稍后调用 fprintf() 和 vfprintf()。

其次是函数的定义。标识符 va_alist 和 va_dcl 是旧式 varargs.h 接口的一部分。

void

#ifdef __STDC__

errmsg(int code, ...)

#else

errmsg(va_alist) va_dcl /* Note: no semicolon! */

#endif

{

/* more detail below */

}

由于旧式可变参数机制不允许指定任何固定参数,因此必须安排在可变部分之前访问它们。此外,由于参数的 "…" 部分缺少名称,新的 va_start() 宏具有第二个参数-"…" 终结符前面的参数的名称。

作为一种扩展,Solaris Studio ISO C 允许在没有固定参数的情况下声明和定义函数,如下所示:

int f(...);

对于此类函数,应在第二个参数为空的情况下调用 va_start(),如下所示:

va_start(ap,)

以下是函数的主体:

{

va_list ap;

char *fmt;

#ifdef __STDC__

va_start(ap, code);

#else

int code;

va_start(ap);

/* extract the fixed argument */

code = va_arg(ap, int);

#endif

if (code & FILENAME)

(void)fprintf(stderr, "\"%s\": ", va_arg(ap, char *));

if (code & LINENUMBER)

(void)fprintf(stderr, "%d: ", va_arg(ap, int));

if (code & WARNING)

(void)fputs("warning: ", stderr);

fmt = va_arg(ap, char *);

(void)vfprintf(stderr, fmt, ap);

va_end(ap);

}

va_arg() 和 va_end() 宏对旧式版本和 ISO C 版本的处理方式相同。由于 va_arg() 更改 ap 的值,因此对 vfprintf() 的调用不能为:

(void)vfprintf(stderr, va_arg(ap, char *), ap);

FILENAME、LINENUMBER 和 WARNING 宏的定义可能包含在与 errmsg() 的声明相同的头文件中。

对 errmsg() 的调用的样例为:

errmsg(FILENAME, "", "cannot open: %s\n",

argv[optind]);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值