programing tip

변수 인수 목록을 허용하는 다른 함수에 변수 인수 전달

itbloger 2020. 8. 27. 07:26
반응형

변수 인수 목록을 허용하는 다른 함수에 변수 인수 전달


그래서 나는 둘 다 비슷한 인수를 갖는 두 개의 함수를 가지고 있습니다.

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

이제를 example호출 exampleB하지만 수정하지 않고 변수 인수 목록의 변수를 어떻게 전달할 수 있습니까 exampleB(이미 다른 곳에서도 사용됨).


직접 할 수는 없습니다. 다음을받는 함수를 만들어야합니다 va_list.

#include <stdarg.h>

static void exampleV(int b, va_list args);

void exampleA(int a, int b, ...)    // Renamed for consistency
{
    va_list args;
    do_something(a);                // Use argument a somehow
    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...
}

여기 연못에 바위를 던질 수도 있지만 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);
}

최소한 g++.


va_list를 받아 전달하는 이러한 함수의 버전을 만들어야합니다. vprintf예를 들어 :

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

또한 printf를 래핑하고 여기에서 유용한 답변을 찾았습니다.

가변 개수의 인수를 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.


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:

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.


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.


A possible way is to use #define:

#define exampleB(int b, ...)  example(0, b, __VA_ARGS__)

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.

참고URL : https://stackoverflow.com/questions/3530771/passing-variable-arguments-to-another-function-that-accepts-a-variable-argument

반응형