将变量参数传递给另一个接受变量参数列表的函数

时间:2022-08-23 16:03:11

So I have 2 functions that both have similar arguments

我有两个函数都有相似的参数

void example(int a, int b, ...);
void exampleB(int b, ...);

Now example calls exampleB, but how can I pass along the variables in the variable argument list without modifying exampleB (as this is already used elsewhere too).

现在示例调用exampleB,但是如何在不修改exampleB的情况下传递变量列表中的变量(因为这在其他地方也已经使用过)。

7 个解决方案

#1


87  

You can't do it directly; you have to create a function that takes a va_list:

你不能直接做;您必须创建一个函数,该函数接受va_list:

#include <stdarg.h>

static void exampleV(int b, va_list args);

void example(int a, int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

void exampleB(int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

static void exampleV(int b, va_list args)
{
    ...whatever you planned to have exampleB do...
    ...except it calls neither va_start nor va_end...
}

#2


14  

you should create versions of these functions which take a va_list, and pass those. Look at vprintf as an example:

您应该创建这些函数的版本,这些函数接受va_list,并传递它们。以vprintf为例:

int vprintf ( const char * format, va_list arg );

#3


6  

Maybe throwin a rock in a pond here, but it seems to work pretty OK with C++11 variadic templates:

也许是在池塘里扔石头,但是用c++ 11变量模板就可以了:

#include <stdio.h>

template<typename... Args> void test(const char * f, Args... args) {
  printf(f, args...);
}

int main()
{
  int a = 2;
  test("%s\n", "test");
  test("%s %d %d %p\n", "second test", 2, a, &a);
}

At the very least, it works with g++.

至少,它适用于g++。

#4


2  

Incidentally, many C implementations have an internal v?printf variation which IMHO should have been part of the C standard. The exact details vary, but a typical implementation will accept a struct containing a character-output function pointer and information saying what's supposed to happen. This allows printf, sprintf, and fprintf to all use the same 'core' mechanism. For example, vsprintf might be something like:

顺便说一句,许多C实现都有一个内部v?印版的变化,IMHO应该是C标准的一部分。具体细节会有所不同,但典型的实现会接受包含字符输出函数指针的结构体,以及说明应该发生什么的信息。这允许printf、sprintf和fprintf都使用相同的“核心”机制。例如,vsprintf可能是这样的:

void s_out(PRINTF_INFO *p_inf, char ch)
{
  (*(p_inf->destptr)++) = ch;
  p_inf->result++;
}

int vsprintf(char *dest, const char *fmt, va_list args)
{
  PRINTF_INFO p_inf;
  p_inf.destptr = dest;
  p_inf.result = 0;
  p_inf.func = s_out;
  core_printf(&p_inf,fmt,args);
}

The core_printf function then calls p_inf->func for each character to be output; the output function can then send the characters to the console, a file, a string, or something else. If one's implementation exposes the core_printf function (and whatever setup mechanism it uses) one can extend it with all sorts of variations.

core_printf函数然后为要输出的每个字符调用p_inf->func;然后,输出函数可以将字符发送到控制台、文件、字符串或其他东西。如果一个人的实现公开了core_printf函数(以及它使用的任何设置机制),那么就可以使用各种变体来扩展它。

#5


1  

I also wanted to wrap printf and found a helpful answer here:

我还想总结printf,在这里找到了一个有用的答案:

How to pass variable number of arguments to printf/sprintf

如何将变量数传递给printf/sprintf

I was not at all interested in performance (I'm sure this piece of code can be improved in a number of ways, feel free to do so :) ), this is for general debugprinting only so I did this:

我对性能一点都不感兴趣(我确信这段代码可以通过多种方式进行改进,请随意这样做:),这只是针对一般的调试打印,所以我这样做了:

//Helper function
std::string osprintf(const char *fmt, ...)
{
    va_list args;
    char buf[1000];
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args );
    va_end(args);
    return buf;
}

which I then can use like this

我可以这样使用它吗

Point2d p;

cout << osprintf("Point2d: (%3i, %3i)", p.x, p.y);
instead of for example:
cout << "Point2d: ( " << setw(3) << p.x << ", " << p.y << " )";

The c++ ostreams are beautiful in some aspects, but practically the become horrific if you want to print something like this with some small strings such as parenthesis, colons and commas inserted between the numbers.

c++ ostreams在某些方面很漂亮,但如果你想打印这样的东西,需要在数字之间插入一些小字符串,比如圆括号、冒号和逗号,那么它就会变得非常可怕。

#6


0  

Based on the comment that you're wrapping vsprintf, and that this is tagged as C++ I'd suggest not trying to do this, but change up your interface to use C++ iostreams instead. They have advantages over the print line of functions, such as type safety and being able to print items that printf wouldn't be able to handle. Some rework now could save a significant amount of pain in the future.

基于您正在包装vsprintf的注释,并将其标记为c++,我建议您不要尝试这样做,而是更改您的接口以使用c++ iostreams。与打印函数相比,它们有一些优势,比如类型安全性和能够打印printf无法处理的项。现在的一些返工可以在未来节省大量的痛苦。

#7


-1  

Using the new C++0x standard, you may be able to get this done using variadic templates or even convert that old code to the new template syntax without breaking anything.

使用新的c++ 0x标准,您可以使用变量模板来完成此任务,甚至可以将旧代码转换为新的模板语法,而不会破坏任何东西。

#1


87  

You can't do it directly; you have to create a function that takes a va_list:

你不能直接做;您必须创建一个函数,该函数接受va_list:

#include <stdarg.h>

static void exampleV(int b, va_list args);

void example(int a, int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

void exampleB(int b, ...)
{
    va_list args;
    va_start(args, b);
    exampleV(b, args);
    va_end(args);
}

static void exampleV(int b, va_list args)
{
    ...whatever you planned to have exampleB do...
    ...except it calls neither va_start nor va_end...
}

#2


14  

you should create versions of these functions which take a va_list, and pass those. Look at vprintf as an example:

您应该创建这些函数的版本,这些函数接受va_list,并传递它们。以vprintf为例:

int vprintf ( const char * format, va_list arg );

#3


6  

Maybe throwin a rock in a pond here, but it seems to work pretty OK with C++11 variadic templates:

也许是在池塘里扔石头,但是用c++ 11变量模板就可以了:

#include <stdio.h>

template<typename... Args> void test(const char * f, Args... args) {
  printf(f, args...);
}

int main()
{
  int a = 2;
  test("%s\n", "test");
  test("%s %d %d %p\n", "second test", 2, a, &a);
}

At the very least, it works with g++.

至少,它适用于g++。

#4


2  

Incidentally, many C implementations have an internal v?printf variation which IMHO should have been part of the C standard. The exact details vary, but a typical implementation will accept a struct containing a character-output function pointer and information saying what's supposed to happen. This allows printf, sprintf, and fprintf to all use the same 'core' mechanism. For example, vsprintf might be something like:

顺便说一句,许多C实现都有一个内部v?印版的变化,IMHO应该是C标准的一部分。具体细节会有所不同,但典型的实现会接受包含字符输出函数指针的结构体,以及说明应该发生什么的信息。这允许printf、sprintf和fprintf都使用相同的“核心”机制。例如,vsprintf可能是这样的:

void s_out(PRINTF_INFO *p_inf, char ch)
{
  (*(p_inf->destptr)++) = ch;
  p_inf->result++;
}

int vsprintf(char *dest, const char *fmt, va_list args)
{
  PRINTF_INFO p_inf;
  p_inf.destptr = dest;
  p_inf.result = 0;
  p_inf.func = s_out;
  core_printf(&p_inf,fmt,args);
}

The core_printf function then calls p_inf->func for each character to be output; the output function can then send the characters to the console, a file, a string, or something else. If one's implementation exposes the core_printf function (and whatever setup mechanism it uses) one can extend it with all sorts of variations.

core_printf函数然后为要输出的每个字符调用p_inf->func;然后,输出函数可以将字符发送到控制台、文件、字符串或其他东西。如果一个人的实现公开了core_printf函数(以及它使用的任何设置机制),那么就可以使用各种变体来扩展它。

#5


1  

I also wanted to wrap printf and found a helpful answer here:

我还想总结printf,在这里找到了一个有用的答案:

How to pass variable number of arguments to printf/sprintf

如何将变量数传递给printf/sprintf

I was not at all interested in performance (I'm sure this piece of code can be improved in a number of ways, feel free to do so :) ), this is for general debugprinting only so I did this:

我对性能一点都不感兴趣(我确信这段代码可以通过多种方式进行改进,请随意这样做:),这只是针对一般的调试打印,所以我这样做了:

//Helper function
std::string osprintf(const char *fmt, ...)
{
    va_list args;
    char buf[1000];
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args );
    va_end(args);
    return buf;
}

which I then can use like this

我可以这样使用它吗

Point2d p;

cout << osprintf("Point2d: (%3i, %3i)", p.x, p.y);
instead of for example:
cout << "Point2d: ( " << setw(3) << p.x << ", " << p.y << " )";

The c++ ostreams are beautiful in some aspects, but practically the become horrific if you want to print something like this with some small strings such as parenthesis, colons and commas inserted between the numbers.

c++ ostreams在某些方面很漂亮,但如果你想打印这样的东西,需要在数字之间插入一些小字符串,比如圆括号、冒号和逗号,那么它就会变得非常可怕。

#6


0  

Based on the comment that you're wrapping vsprintf, and that this is tagged as C++ I'd suggest not trying to do this, but change up your interface to use C++ iostreams instead. They have advantages over the print line of functions, such as type safety and being able to print items that printf wouldn't be able to handle. Some rework now could save a significant amount of pain in the future.

基于您正在包装vsprintf的注释,并将其标记为c++,我建议您不要尝试这样做,而是更改您的接口以使用c++ iostreams。与打印函数相比,它们有一些优势,比如类型安全性和能够打印printf无法处理的项。现在的一些返工可以在未来节省大量的痛苦。

#7


-1  

Using the new C++0x standard, you may be able to get this done using variadic templates or even convert that old code to the new template syntax without breaking anything.

使用新的c++ 0x标准,您可以使用变量模板来完成此任务,甚至可以将旧代码转换为新的模板语法,而不会破坏任何东西。