I've seen constructs like these in a lot of programs:
/**
* mydebug.h -- freeware
*/
/* Prevent mydebug.h from being included more than once */
#ifndef __MYDEBUG_H__
#define __MYDEBUG_H__
/* Makes these functions work even if you include and use this in a .cpp file */
#ifdef __cplusplus
extern "C" {
#endif
/* Don't call directly, use DEBUG_PRINT(("something")) macros */
void _debug_print(const char *cmdstr, ...);
void _info_print(const char *cmdstr, ...);
#ifdef __cplusplus
}
#endif
/**
* INFO_PRINT always calls _info_print, even if it might NOT actually print anything,
* so use it sparingly, it'll bloat the final program.
*/
#define INFO_PRINT(X) _info_print X
/**
* Will ONLY be called when DEBUG is defined, should magically disappear
* otherwise. Use all you want, will not bloat non-DEBUG builds.
*/
#ifdef DEBUG
#define DEBUG_PRINT(X) _debug_print X
#else
#define DEBUG_PRINT(X)
#endif
#endif/*__MYDEBUG_H__*/
/**
* mydebug.c -- freeware
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "mydebug.h"
void _debug_print(const char *cmdstr, ...)
{
va_list ap;
va_start(ap,cmdstr);
vfprintf(stderr,cmdstr,ap);
va_end(ap);
}
void _info_print(const char *cmdstr, ...)
{
va_list ap;
/**
* When DEBUG is undefined, it checks for the DEBUG environment variable.
* Otherwise, it always prints.
*/
#ifndef DEBUG
if(getenv("DEBUG") == NULL) return;
#endif
va_start(ap,cmdstr);
vfprintf(stderr,cmdstr,ap);
va_end(ap);
}
This moves all the crazy preprocessor things into a header file and source file so you don't have to worry about whether they should be printing or not.
These functions also behave exactly like printf, because they just pass all their arguments to printf.
/**
* debugtest.c -- freeware
*/
#include "mydebug.h"
int main()
{
DEBUG_PRINT(("This should only print when DEBUG's defined in preprocessor %d\n",5));
INFO_PRINT(("If DEBUG is defined, this always prints\n"));
INFO_PRINT(("If DEBUG isn't defined, it only prints if DEBUG is in the environment\n"));
return(0);
}
Note the crazy double brackets. These are there because most compilers cannot handle variable numbers of arguments inside preprocessor macros; the whole bracketed mess becomes one paramater, so DEBUG_PRINT(("something")) becomes _debug_print ("something") .
That I've seen this reimplimented time and time again in so many programs suggests to me there's no "standard" way.