提问人:KianFakheriAghdam 提问时间:10/7/2022 最后编辑:Peter MortensenKianFakheriAghdam 更新时间:10/29/2022 访问量:385
va_list in C:创建一个不需要参数计数的函数,如“printf”
va_list in C: Creating a function that doesn't need a argument count like 'printf'
问:
使用标头,可以创建一个具有可变数量参数的函数,但是:<stdarg.h>
要开始使用 ,您需要使用一个宏,该宏需要知道有多少个参数,但是 & ...使用不需要参数计数。我怎样才能创建一个不需要参数计数的函数,比如?
va_list
va_start
printf
va_list
printf
假设我想创建一个函数,该函数接受 ?(所以在伪代码中,它会像
va_list
va_list
void printfRipOff(const char* format, ...) {printf(format, ...);}
)
答:
函数喜欢 和 具有格式字符串参数,该参数告诉它们函数调用必须提供的参数的数量和类型。
printf()
scanf()
如果你正在编写自己的函数,你必须有某种方法来知道提供了多少个参数及其类型。可能它们都是同一种类型。可能它们都是指针,您可以使用空指针来指示参数的结尾。否则,您可能必须包括一个计数。
只要被调用的函数需要 .有一些警告(参见 C11 §7.16 变量参数),但只要稍加努力,它们就可以管理。
va_list
一个非常常见的习语是,你有一个函数和第二个函数,你把第一个实现为对第二个的简单调用:int sometask(const char *fmt, ...)
int vsometask(const char *fmt, va_list args)
int sometask(const char *fmt, ...)
{
va_list args;
va_start(fmt, args);
int rc = vsometask(fmt, args);
va_end(args);
return rc;
}
当然,第二个函数执行实际工作,或者调用其他函数来执行实际工作。
在问题中,你说:
... 需要知道多少参数的宏......
va_start
不;宏只需要知道省略号前面的参数是哪个参数 — 函数定义中 之前的参数名称。va_start
, ...
在评论中,你说:
这就是我想写的,但它没有用。
string format(const char* text, ...) { // temporary string used for formatting string formattedString; initializeString(&formattedString, text); // start the va_list va_list args; va_start(text, args); // format sprintf(formattedString.array, text, args); // end the va_list va_end(args); return formattedString; }
正如 abelenky 在评论中指出的那样,您需要使用:vsprintf()
string format(const char* text, ...)
{
string formattedString;
initializeString(&formattedString, text);
va_list args;
va_start(text, args);
vsprintf(formattedString.array, text, args);
va_end(args);
return formattedString;
}
这假设数组中有足够的空间来存储格式化的结果。它是如何组织的并不明显,但想必你知道它是如何工作的,而且它是安全的。如果可以确定 中的可用空间,请考虑使用 。formattedString
vsnprintf()
formattedString
评论
string format(const char* text, ...) { // temporary string used for formatting string formattedString; initializeString(&formattedString, text); // start the va_list va_list args; va_start(text, args); // format sprintf(formattedString.array, text, args); // end the va_list va_end(args); return formattedString; }
vsprintf
sprintf
v
cs50
string
C
C
char *
string
string
malloc
函数的 and 系列不需要显式传递 的长度,因为它们能够通过格式字符串推断参数的数量。printf
scanf
va_list
例如,在像这样的通话中:
printf("%d %c %s\n", num, c, "Hello");
printf
能够检查第一个参数,即格式字符串,并看到它按该顺序包含 a、a 和 a,因此它可以假设有三个附加参数,其中第一个是 a,第二个是 a,第三个是 a,它可能假定它是指向以 null 结尾的字符串的指针。%d
%c
%s
signed int
char
char*
要编写一个不需要明确告知正在传递多少个参数的类似函数,您必须找到一种方法来巧妙地为它提供一些信息,使其能够推断出 中参数的数量和类型。va_list
假设我想创建一个接受va_list
的函数,而不是使用它,而是将其传递给另一个需要va_list
的函数?
查看函数,了解将 a 作为输入参数的函数的一个示例。vprintf( const char * format, va_list arg );
va_list
它基本上是这样使用的:
#include <stdio.h>
#include <stdarg.h>
void CountingPrintf(const char* format, ...)
{
static int counter = 1;
printf("Line # %d: ", counter++); // Print a Counter up front
va_list args;
va_start(args, format); // Get the args
vprintf(format, args); // Pass the "args" through to another printf function.
va_end(args);
}
int main(void) {
CountingPrintf("%s %s\n", "Hello", "World");
CountingPrintf("%d + %d == %d\n", 2, 3, 2+3);
return 0;
}
输出:
Line # 1: Hello World
Line # 2: 2 + 3 == 5
评论
va_start macro that needs to know how many arguments there
va_start
宏不需要知道有多少个参数。 “知道”参数计数 - 它计算格式字符串中不跟另一个字符串的数量。 这么说吧,还有?所以写那个函数。How can I create a function that doesn't need the argument count like printf?
printf
%
%
say I want to create a function that takes a va_list & instead of using it, passes it to another function that requires a va_list?
sprintf
并且是相同的,只是打印到和打印到作为第一个参数传递的参数printf
printf
stdout
sprintf
char*