LO19810527
asked on
Macro that can take variable qty of arguments
How can I make a macro that can take variable qty of arguments.
#ifdef DEBUG
#define DEBUG_OUTPUT(Data) print_debug(Data)
#else
#define DEBUG_OUTPUT(Data)
#endif
void function_x(int xyz)
{
DEBUG_OUTPUT("function_x(% i)", xyz);
}
void Widgit_func(int xyz, string somedat)
{
DEBUG_OUTPUT("Widgit_func( %i, %s)", xyz, somedat.c_str());
}
I need DEBUG_OUTPUT marco that can take any number of arguments.
#ifdef DEBUG
#define DEBUG_OUTPUT(Data) print_debug(Data)
#else
#define DEBUG_OUTPUT(Data)
#endif
void function_x(int xyz)
{
DEBUG_OUTPUT("function_x(%
}
void Widgit_func(int xyz, string somedat)
{
DEBUG_OUTPUT("Widgit_func(
}
I need DEBUG_OUTPUT marco that can take any number of arguments.
#ifdef DEBUG
#define DEBUG_OUTPUT MyPrintf
#else
#define DEBUG_OUTPUT EmptyPrint
#endif
#include <stdio.h>
#include <stdarg.h>
void MyPrintf( char *s, ... )
{
}
void MyPrintf( char *s, ... )
{
va_list argList;
char msg[3000];
va_start( argList, s );
vsprintf( msg, s, argList);
va_end( argList );
printf("%s\n", msg );
}
int main()
{
MyPrintf("%s %d", "Hello", 123);
return 1;
}
#define DEBUG_OUTPUT MyPrintf
#else
#define DEBUG_OUTPUT EmptyPrint
#endif
#include <stdio.h>
#include <stdarg.h>
void MyPrintf( char *s, ... )
{
}
void MyPrintf( char *s, ... )
{
va_list argList;
char msg[3000];
va_start( argList, s );
vsprintf( msg, s, argList);
va_end( argList );
printf("%s\n", msg );
}
int main()
{
MyPrintf("%s %d", "Hello", 123);
return 1;
}
BTW, just in case you weren't already aware of that: No other compiuler supports the construct of a 'macro taking a variable number of arguments', so you will eventually either end up having to use a function to perform that or use multiple macros that take account of the number of arguments you're passing, e.g. like
#ifdef DEBUG
#define DEBUG_OUTPUT1(d1) print_debug(d1)
#define DEBUG_OUTPUT2(d1, d2) print_debug(d1, d2)
// etc.pp.
#else
//...
#endif
#ifdef DEBUG
#define DEBUG_OUTPUT1(d1) print_debug(d1)
#define DEBUG_OUTPUT2(d1, d2) print_debug(d1, d2)
// etc.pp.
#else
//...
#endif
thienpnguyen, your suggestion still involves an 'unnecessary' function call - and, BTW, I'd personally make it read
void MyPrintf( char *s, ... )
{
#ifdef DEBUG
//...
#endif
}
void MyPrintf( char *s, ... )
{
#ifdef DEBUG
//...
#endif
}
>>your suggestion still involves an 'unnecessary' function call
Which isn't really too bad, actually :o)
Which isn't really too bad, actually :o)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
FYI:
The VC method does have one bad side effect.
Example:
//This works OK
void function_x(int xyz)
{
DEBUG_PRINT("function_x(%i )", xyz);
printf("Hello World");
}
//This will NOT works OK
void function_x(int xyz)
{
if (xyz == 123) DEBUG_PRINT("function_x(%i )", xyz);
printf("Hello World");
}
In NON-Debug mode, the compiler will see the second code like this:
if (xyz == 123) printf("Hello World");
You don't have this problem with the GNUC method.
The VC method does have one bad side effect.
Example:
//This works OK
void function_x(int xyz)
{
DEBUG_PRINT("function_x(%i
printf("Hello World");
}
//This will NOT works OK
void function_x(int xyz)
{
if (xyz == 123) DEBUG_PRINT("function_x(%i
printf("Hello World");
}
In NON-Debug mode, the compiler will see the second code like this:
if (xyz == 123) printf("Hello World");
You don't have this problem with the GNUC method.
ASKER
jkr,
I tried your gcc method, but it failed to compile.
It seems like the correct syntax is the one posted by Axter.
Axter,
I tried your macro, and much to my surprise, it works on all the compilers I tested. I did modify it a little.
#ifdef DEBUG
#ifdef __GNUC__
#define DEBUG_OUTPUT(args...) print_debug(args)
#else
#define DEBUG_OUTPUT print_debug
#endif //__GNUC__
#else
#ifdef __GNUC__
#define DEBUG_OUTPUT(args...)
#else
#define DEBUG_OUTPUT ;/##/
#endif //__GNUC__
#endif //DEBUG
I added ";" before /##/
This will remove the bad side effect you posted. The only down side to this modification is that it produces a warning on some compilers. But I rather get the warning then to have the side effects.
I tried your gcc method, but it failed to compile.
It seems like the correct syntax is the one posted by Axter.
Axter,
I tried your macro, and much to my surprise, it works on all the compilers I tested. I did modify it a little.
#ifdef DEBUG
#ifdef __GNUC__
#define DEBUG_OUTPUT(args...) print_debug(args)
#else
#define DEBUG_OUTPUT print_debug
#endif //__GNUC__
#else
#ifdef __GNUC__
#define DEBUG_OUTPUT(args...)
#else
#define DEBUG_OUTPUT ;/##/
#endif //__GNUC__
#endif //DEBUG
I added ";" before /##/
This will remove the bad side effect you posted. The only down side to this modification is that it produces a warning on some compilers. But I rather get the warning then to have the side effects.
Just out of curiousity, what compilers did you test it on?
ASKER
I tested it in Visual C++ 6.0, Window/DOS GNU compiler, Borland (BC4), C++ Builder 5, Turbo C++ 3.0 and 4.5
With the modification I made, it gave a warning in Turbo C++ 3.0 and 4.5
With the modification I made, it gave a warning in Turbo C++ 3.0 and 4.5
#define DEBUG_OUTPUT(...) print_debug(...)
This won't work with other compilers, though...