가변 수의 인수를 취하는 C 함수가 있다고 가정 해보십시오. 첫 번째 함수에있는 모든 인수를 전달하여 내부에서 가변 수의 인수를 기대하는 다른 함수를 어떻게 호출 할 수 있습니까?
예:
void format_string(char *fmt, ...);
void debug_print(int dbg_lvl, char *fmt, ...) {
format_string(fmt, /* how do I pass all the arguments from '...'? */);
fprintf(stdout, fmt);
}
답변
타원을 전달하려면 타원을 va_list로 변환하고 두 번째 함수에서 해당 va_list를 사용해야합니다. 구체적으로 특별히;
void format_string(char *fmt,va_list argptr, char *formatted_string);
void debug_print(int dbg_lvl, char *fmt, ...)
{
char formatted_string[MAX_FMT_SIZE];
va_list argptr;
va_start(argptr,fmt);
format_string(fmt, argptr, formatted_string);
va_end(argptr);
fprintf(stdout, "%s",formatted_string);
}
답변
당신이 장난스럽고 휴대 할 수없는 트릭에 들어가고 싶지 않다면, 얼마나 많은 인수를 전달했는지 알지 못하고 printf를 호출하는 방법은 없습니다.
일반적으로 사용되는 솔루션은 그래서 항상 가변 인자 함수의 대체 양식을 제공하는 printf
이 vprintf
소요되는 va_list
의 장소에서 ...
. ...
버전은 주변 단지 래퍼 va_list
버전.
답변
다양한 기능 이 위험 할 수 있습니다 . 더 안전한 트릭이 있습니다.
void func(type* values) {
while(*values) {
x = *values++;
/* do whatever with x */
}
}
func((type[]){val1,val2,val3,val4,0});
답변
멋진 C ++ 0x에서는 가변 템플릿을 사용할 수 있습니다.
template <typename ... Ts>
void format_string(char *fmt, Ts ... ts) {}
template <typename ... Ts>
void debug_print(int dbg_lvl, char *fmt, Ts ... ts)
{
format_string(fmt, ts...);
}
답변
함수 호출에 인라인 어셈블리를 사용할 수 있습니다. (이 코드에서는 인수가 문자라고 가정합니다).
void format_string(char *fmt, ...);
void debug_print(int dbg_level, int numOfArgs, char *fmt, ...)
{
va_list argumentsToPass;
va_start(argumentsToPass, fmt);
char *list = new char[numOfArgs];
for(int n = 0; n < numOfArgs; n++)
list[n] = va_arg(argumentsToPass, char);
va_end(argumentsToPass);
for(int n = numOfArgs - 1; n >= 0; n--)
{
char next;
next = list[n];
__asm push next;
}
__asm push fmt;
__asm call format_string;
fprintf(stdout, fmt);
}
답변
매크로도 시도해 볼 수 있습니다.
#define NONE 0x00
#define DBG 0x1F
#define INFO 0x0F
#define ERR 0x07
#define EMR 0x03
#define CRIT 0x01
#define DEBUG_LEVEL ERR
#define WHERESTR "[FILE : %s, FUNC : %s, LINE : %d]: "
#define WHEREARG __FILE__,__func__,__LINE__
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define DEBUG_PRINT(X, _fmt, ...) if((DEBUG_LEVEL & X) == X) \
DEBUG(WHERESTR _fmt, WHEREARG,__VA_ARGS__)
int main()
{
int x=10;
DEBUG_PRINT(DBG, "i am x %d\n", x);
return 0;
}
답변
포맷터를 로컬 버퍼에 먼저 저장하여 전달할 수는 있지만 스택이 필요하고 때로는 문제가 될 수 있습니다. 나는 다음을 시도했지만 정상적으로 작동하는 것 같습니다.
#include <stdarg.h>
#include <stdio.h>
void print(char const* fmt, ...)
{
va_list arg;
va_start(arg, fmt);
vprintf(fmt, arg);
va_end(arg);
}
void printFormatted(char const* fmt, va_list arg)
{
vprintf(fmt, arg);
}
void showLog(int mdl, char const* type, ...)
{
print("\nMDL: %d, TYPE: %s", mdl, type);
va_list arg;
va_start(arg, type);
char const* fmt = va_arg(arg, char const*);
printFormatted(fmt, arg);
va_end(arg);
}
int main()
{
int x = 3, y = 6;
showLog(1, "INF, ", "Value = %d, %d Looks Good! %s", x, y, "Infact Awesome!!");
showLog(1, "ERR");
}
도움이 되었기를 바랍니다.