prev up next   top/contents search

comp.lang.c FAQ 列表· 问题 15.12

Q我如何编写一个接受可变数量参数并将其传递给另一个函数(该函数也接受可变数量参数)的函数?


A一般来说,你不能。理想情况下,你应该提供该其他函数的一个版本,该版本接受一个va_list指针,会发生什么。

假设您想编写一个faterror函数,该函数将打印一个致命错误消息,然后退出。您可能希望将其写成基于函数(来自第 15.5 题)的一个版本,使用了问题 15.5 的函数

	void faterror(const char *fmt, ...)
	{
		error(fmt, what goes here? );
		exit(EXIT_FAILURE);
	}
但如何处理尚不清楚faterror的参数传递给函数(来自第 15.5 题)的一个版本,使用了.

执行以下操作。首先,拆分现有的函数(来自第 15.5 题)的一个版本,使用了函数以创建一个新的verror该函数不接受可变参数列表,而是接受一个单独的va_list指针。 (请注意,这样做只是做了很少的额外工作,因为verror包含了很多以前在函数(来自第 15.5 题)的一个版本,使用了中使用的代码,而新的函数(来自第 15.5 题)的一个版本,使用了成为一个简单的包装器,围绕着verror.)

#include <stdio.h>
#include <stdarg.h>

void verror(const char *fmt, va_list argp)
{
	fprintf(stderr, "error: ");
	vfprintf(stderr, fmt, argp);
	fprintf(stderr, "\n");
}

void error(const char *fmt, ...)
{
	va_list argp;
	va_start(argp, fmt);
	verror(fmt, argp);
	va_end(argp);
}

现在你可以写faterror,并让它调用verror,也可以

#include <stdlib.h>

void faterror(const char *fmt, ...)
{
	va_list argp;
	va_start(argp, fmt);
	verror(fmt, argp);
	va_end(argp);
	exit(EXIT_FAILURE);
}
请注意,之间的关系函数(来自第 15.5 题)的一个版本,使用了verror正是 e.g. 之间的关系printfvprintf。事实上,正如 Chris Torek 所观察到的,每当您发现自己编写一个 varargs 函数时,最好编写它的两个版本:一个(如verror)接受一个va_list并完成工作,另一个(如修改后的函数(来自第 15.5 题)的一个版本,使用了)是一个简单的包装器。唯一的真正限制是,像verror这样的函数只能扫描一次参数;无法重新调用 va_start。

如果您没有选择重写较低级别的函数(函数(来自第 15.5 题)的一个版本,使用了在此示例中)以接受一个va_list,因此您发现自己需要将一个函数(例如faterror)接收到的可变参数传递给另一个作为实际参数,则不可能有可移植的解决方案。 (问题也许可以通过诉诸机器特定的汇编语言来解决;另请参阅问题 15.13。)

一种不会起作用的方法是这样的

	void faterror(const char *fmt, ...)
	{
		va_list argp;
		va_start(argp, fmt);
		error(fmt, argp);		/* WRONG */
		va_end(argp);
		exit(EXIT_FAILURE);
	}
Ava_list本身并不是一个可变参数列表;它实际上是一种指向它的指针。也就是说,一个接受va_list的函数本身不是 varargs,反之亦然。

另一种有时被使用,并且有时有效但严重不便携的解决方法是使用大量的int参数,希望有足够的参数,并且它们能够以某种方式传递指针、浮点和其他参数

	void faterror(fmt, a1, a2, a3, a4, a5, a6)
	char *fmt;
	int a1, a2, a3, a4, a5, a6;
	{
		error(fmt, a1, a2, a3, a4, a5, a6);	/* VERY WRONG */
		exit(EXIT_FAILURE);
	}
此示例仅用于劝您不要使用它;请不要仅仅因为在这里看到它就尝试。


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管