I want to enable "printf("macro MESSAGE is %d\n",MESSAGE);" during run time. For example , if i give argument 10 in run time, it should print the message. if it is not given, it should not print this message.Is it possible?
#include <stdio.h>
#define MESSAGE 10
int foo;
void main(int argc, char *argv[])
{
foo = atoi(argv[1]);
printf("foo is %d\n", foo);
#if MESSAGE==foo
printf("macro MESSAGE is %d\n",MESSAGE);
#endif
}
We can define a macro conditionally based on a preprocessor macro to control in compile time what the definition of the macro is:
#if DEBUGGING
#define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)
#else
#define debug(format, ...) ()
#endif
The debug macro itself is actually an example in GCC's manual.
Or, we could make a similar function that checks in run time the value of some variable:
#include <stdarg.h>
#include <stdio.h>
int debugging = 10;
void debug(int msglevel, const char *fmt, ...)
{
if (debugging < msglevel) return;
va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
}
...
debug(10, "Error: %s\n", "some explanation");
A full function makes it easier to do a greater than comparison for the verbosity level. Of course we could still have an alternate definition of r the function on compile time to fully disable it. For the varargs, see the va_arg(3) man page.
Related
Is there a way to define a macro that voids variable list of arguments?
#define VOID_ARGS(...) ((void)##__VA_ARGS__)
The use case is void arguments to suppress compiler error [-Werror=unused-value] when warnings treated as errors:
#define DEBUG 1
#ifdef DEBUG
#define func(fmt, ...) dbg_func(fmt, ##__VA_ARGS__)
#else
#define func(fmt, ...) VOID_ARGS(fmt, ##__VA_ARGS__)
#endif
Does this give you an idea how to solve that problem?
debug.h:
extern int dbg_func(const char *format, ...);
//Does nothing
extern int ignoreDebug(const char *format, ...);
#define DEBUG 1
#ifdef DEBUG
#define func(fmt, ...) dbg_func(fmt, ##__VA_ARGS__)
#else
#define func(fmt, ...) ignoreDebug(fmt, ##__VA_ARGS__)
#endif
debug.c:
int ignoreDebug(const char *format, ...)
{
(void)format;
return 0;
}
int dbg_func(const char *format, ...)
{
TODO: Some code needs to go here.
return 0;
}
Rather than attempting to put the debug logic in the function declaration, add it to the function body instead:
int dbg_func(const char *format, ...)
{
#ifdef DEBUG
// normal debug logic
#else
(void)format;
return 0;
#endif
}
I found a way only using the processor. The idea came from this answer https://stackoverflow.com/a/11763277/6082851 The idea is to define a bunch of macros that void the arguments, one macro per possible number of arguments. With the use of __VA_ARGS__, the correct macro can be chosen depending on the number of arguments. Sadly, i didn't found a way to make it recursive so that a limited number of macros can be used for an arbitrary number of arguments, the only way i found was to define a macro for each possible number of arguments. But it can be expanded to an arbitrary amount.
#include <stdio.h>
#ifndef DEBUG
#define DEBUG 1
#endif
#if DEBUG
#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)
#else
//GET_MACRO will get the 6. argument
#define GET_MACRO(a,b,c,d,e,f,...) f
//Macros that void a number of arguments
#define SET_VOID0()
#define SET_VOID1(a) (void)a;
#define SET_VOID2(a,b) (void)a;(void)b;
#define SET_VOID3(a,b,c) (void)a;(void)b;(void)c;
#define SET_VOID4(a,b,c,d) (void)a;(void)b;(void)c;(void)d;
#define SET_VOID5(a,b,c,d,e) (void)a;(void)b;(void)c;(void)d;(void)e;
//Void all arguments to avoid compiler warnings.
//SET_VOID5 is used when there are 5 arguments used, SET_VOID4 when 4 are used, ...
#define DEBUG_PRINT(...) GET_MACRO(__VA_ARGS__, SET_VOID5, SET_VOID4, SET_VOID3, SET_VOID2, SET_VOID1, SET_VOID0)(__VA_ARGS__)
#endif
int main(void)
{
int foo=5;
int bar=3;
DEBUG_PRINT("Foo %i Bar %i\n",foo,bar);
return 0;
}
Im trying to make my defines can be switched during runtime, so I cant enable/disable printing some info.
I have next files:
main.c
config.c
config.h (included in both c files)
in config.c :
//define DEBUG // <--------------- COMMENT THIS TO SWITCH PRINT/NOT PRINT
#define PRINTF(fmt, ...) printf("TAG: " fmt "\n", ## __VA_ARGS__)
#ifdef DEBUG
#define DPRINTF PRINTF
#else
#define DPRINTF(...) do {} while (0)
#endif
int foo()
{
...
if(error){
PRINTF("error happens, code %d", code);
}
else{
DPRINF("all good, all parameters: [%d][%d]", par1, par2);
}
}
(short explanation: if DEBUG defined then macro DPRINTF will print some info, otherwise do nothing)
What I want is be able to dynamically switch it from main.c somehow, instead of comment / uncomment and recompile program.
So my idea was to set in config.h
extern uint8_t dbg_status;
#define DGB_ON (1)
#define DGB_OFF (0)
#define ENABLE_DBG (dbg_status? (DGB_ON) : (DGB_OFF))
And in main.c do something like that:
uint8_t dbg_status;
int main(int argc, char** argv)
{
// enable debug if run with next argument:
// program.exe -DEBUG
if (!strcmp(argv[1], "-DEBUG"))
{
// enable debug prints
dbg_status= 1;
}
else
{
// disable debug prints
dbg_status= 0;
}
...
}
But Im stuck with it now, I dont know what to do next...
Add some additional defines in config.c?
#if (ENABLE_DEBUG)
#define DEBUG
#endif
I feel that Im on right way, but dont see where to move next.
UPD:
Original idea from here:
Changing a macro at runtime in C
But Im stuck with realization...
You could use something like this:
int debugflag = 0;
void DPRINTF(char *format, ...) {
if (!debugflag)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
}
Now you can choose dynamically with the global variable debugflag if you want the debug output or not.
With macros, this is not possible directly, since these are evaluated at compile time and cannot be influenced at runtime directly.
I'm looking to write what I would imagine is a fairly common macro. I want to emulate the repeated "-v" options on many POSIX programs by defining a bunch of macros of the following form:
#define V1(str, ...) if(optv >= 1){printf("%s: "str,prog,__VA_ARGS__);}
int main(int argc, char* argv[])
{
// ... stuff ...
int i = 1;
V1("This contains a variable: %d\n",i);
}
// Output:
// ./program: This contains a variable: 1
where optv counts the number of "-v" options found on the command line and prog contains the program name (neither shown). This works well, but the problem is that I have to use a variable. V1("Output") will generate a compiler error. I could always use V1("Output%s","") but there should be a cleaner solution.
The GNU C preprocessor has a special feature that lets you delete the trailing comma when there are no arguments filling the variadic portion by prepending the token-pasting operator ## to __VA_ARGS__:
#define V1(str, ...) if(optv < 1); else printf("%s: "str,prog, ## __VA_ARGS__)
Alternatively, if you wish to remain fully C99 compliant, you could incorporate the the format string parameter into the ellipsis, but in this instance you'll also need to refactor your code since you want to include the extra prog parameter between the format string and the varargs. Something like this might work:
#define V1(...) if(optv < 1); else myprintf(prog, __VA_ARGS__)
int myprintf(const char *prog, const char *fmt, ...)
{
// Print out the program name, then forward the rest onto printf
printf("%s: ", prog);
va_list ap;
va_start(ap, fmt);
int ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
Then, V1("Output") expands to myprintf(prog, "Output") without using any non-C99 compiler extensions.
EDIT
Also note that I inverted the if condition in the macro, due to some weird issues that can arise if you invoke the macro inside an if statement without braces—see this FAQ for a detailed explanation.
Why don't you use 2 different macros for each verbosity level; one which prints a message and variable, and one which just prints a message?
You should probably write yourself a small support function so that you can do the job cleanly:
extern void vb_print(const char *format, ...);
#define V1(...) do { if (optv >= 1) vb_print(__VA_ARGS__); } while (0)
I assume that both optv and prog are global variables. These would go into a header (you wouldn't write them out in the programs themselves, would you?).
The function can be:
#include <stdio.h>
#include <stdarg.h>
extern const char *prog;
void vb_print(const char *format, ...)
{
va_list args;
va_start(args, format);
printf("%s:", prog);
vprintf(format, args);
va_end(args);
}
There's no rocket science in there. You can tweak the system to your heart's content, allowing a choice of where the information is written, flushing the output, ensuring there's a newline at the end, etc.
Try this:
#define V1X(str, ...) if(optv >= 1) {printf("%s: "str,prog,__VA_ARGS__);} else
#define V1(...) V1X(__VA_ARGS__,0)
I believe that fixes the problem you described, and the else at the end fixed another problem.
I got stuck here...
#include <stdio.h>
#define DBG_LVL(lvl, stmt) \
do{ \
if(lvl>1) printf stmt; \
}while(0)
#define DBG_INFO(stmt) DBG_LVL(1, stmt)
#define DBG_ERROR(stmt) DBG_LVL(2, stmt)
int main()
{
DBG_INFO(("hello, %s!\n", "world"));
DBG_ERROR(("crazy, %s!\n", "world"));
return 0;
}
As you can see, the code above uses macros like "DBG_INFO" or "DBG_ERROR" to control debug information level.
Now for some reason, I have to replace DBG_LVL() with a new function.
void myprint(int lvl, const char * format, ...);
The only difference is the debug level is taken as its fisrt parameter.
I was thinking:
#define DBG_LVL(lvl, stmt) myprint(lvl, stmt)
Of course it failed, because the "stmt" expression includes parentheses around.
Then I googled around trying to find a way to strip the parentheses, seems there's nothing could help.
I also tried some tricks to pass parameters into "stmt", still failed... :(
Can you help me?
# define EXPAND_ARGS(...) __VA_ARGS__
# define DBG_LVL(lvl, stmt) myprint(lvl, EXPAND_ARGS stmt);
Don't write this as a macro.
Write instead an ordinary varargs function:
void DBG_LVL(int level, char *fmt, ...)
{
if (level < 1) return;
va_list args;
va_start(args, fmt);
vaprintf(fmt, args);
va_end(args);
}
For myprint(), define a similar vamyprint(int lvl, const char *format, va_list ap) as well, and forward the same way.
For debugging purposes I would like to have a printf_debug function that would function just like the standard printf function, but would only print if a #DEFINE DEBUG was true
I know I have to use varagrs (...) but I have no idea how to actually achieve that.
Thanks in advance.
Easier to just #define it away. Something like this:
#ifdef DEBUG
#define printf_debug printf
#else
#define printf_debug while(0)printf
#endif
I don't what exactly you want to achieve. In case you want a code block to execute only if DEBUG is defined, use the preprocessor directive #ifdef.
#include <stdio.h>
#include <stdarg.h>
#define DEBUG
void printf_debug(const char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
#endif /* DEBUG */
}
You don't need to use vargs, macros will work. Here is an example, which will prints function and line number as well:
#ifdef DEBUG
#define printf_debug(fmt, args...) printf("%s[%d]: "fmt, __FUNCTION__, __LINE__, ##args)
#else
#define printf_debug(fmt, args...)
#endif
The ##args here will be replaced by the args list, which likes what vargs does in function call.
You have to use the va_arg macros, they are used to access the variadic variables. A useful link: http://www.cppreference.com/wiki/c/other/va_arg. The reference is for C++, but these macros can be used in C as well.
In your actual implementation you place the code using the variadic variables in a #ifdef block.
But if you're looking for a regular call to printf, dependent on DEBUG a simple #define acting as an alias will do.
C99 compiler only!
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug(...) printf(__VA_ARGS__)
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}
to be honest varidic macros are not needed you could just easily write it as this:
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug printf
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}
Thinking about it, debug information should go to stderr so as not to interfer with stdout, so this one should be favoured:
#include <stdio.h>
#define DEBUG
#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug while(0)
#endif
int main(int argc, char *argv[])
{
debug("Only shows when DEBUG is defined!\n");
return 0;
}