0

I've added a bunch of "debug(x)" statements to my code using preprocessing macros in a header file. I've also implemented a toggle (via an #ifdef / #else structure in the header file) that lets me turn off the debug statements. I'm having trouble getting this toggle to work and am hoping someone can figure out the reason.

Rather than re-posting the actual code (which is lengthy), I'm including an illustrative example (which does compile).

Here's our .h file. It consists of a macro for a function named "superman". The statement should print if and only if KRYPTONITE is not defined in our .c file.

test.h:

#ifndef __test_h__
#define __test_h__

#ifdef KRYPTONITE
#define superman(...)
#else
#define superman(xs) printf("%s\n\n",xs)
#endif

#endif

As you can see in the cases below, adding a "#define KRYPTONITE 1" statement to the beginning of our .c file does not toggle off the "superman" function (Case 2 below). However, we do successfully toggle off if we define KRYPTONITE via a flag in our compile instruction (Case 3).

What else do I need to do in order to toggle off the "superman" function via a "#define" statement in the .c file?


Case 1: KRYPTONITE not defined in the .c file (it's commented out). As expected, the statement prints. (The .c file and output is below.)

test1.c:

#include <stdio.h>
#include "test.h"
//#define KRYPTONITE

int main (int argc, char *argv[])
{
  printf("\nSuperman, are you here?\n\n");
  superman("I'm here");
  return 0;
}

Output:

dchaudh@dchaudhUbuntu:~/SO$ gcc test1.c -o test1
dchaudh@dchaudhUbuntu:~/SO$ ./test1

Superman, are you here?
I'm here

dchaudh@dchaudhUbuntu:~/SO$

Case 2: KRYPTONITE is defined in our .c file, yet the statement prints.

test2.c:

#include <stdio.h>
#include "test.h"

#define KRYPTONITE

int main (int argc, char *argv[])
{
  printf("\nSuperman, are you here?\n\n");
  superman("I'm here");
  return 0;
}

Output:

dchaudh@dchaudhUbuntu:~/SO$ gcc test2.c -o test2
dchaudh@dchaudhUbuntu:~/SO$ ./test2

Superman, are you here?
I'm here

dchaudh@dchaudhUbuntu:~/SO$

Case 3: KRYPTONITE is not defined in our .c file but we define it via a flag when compiling. In this case, the superman function is successfully toggled off.

Output:

dchaudh@dchaudhUbuntu:~/SO$ gcc -DKRYPTONITE test1.c -o test3
dchaudh@dchaudhUbuntu:~/SO$ ./test3

Superman, are you here?

dchaudh@dchaudhUbuntu:~/SO$
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
iceman
  • 2,020
  • 2
  • 17
  • 24
  • 3
    Unrelated, but technically, and by the specification, symbols with two leading underscores is reserved for use by the compiler and standard library. – Some programmer dude Oct 11 '14 at 23:13
  • 1
    A small tip for using this kind of macro for logging purposes: The C99 preprocessor supports variadic macros and MSVC also has them. There's just a slight difference in the way, trailing commas in the expansion are handled. for example `#define log_printf(l, fmt, ...) fprintf(stderr, "%c: " fmt, l, __VA_ARGS__)`. However with GCC this requires to always supply additional arguments, which MSVC silently resolves this case. GCC however has the extension that you can write `#__VA_ARGS__` instead. – datenwolf Oct 11 '14 at 23:22
  • @datenwolf At the moment I'm using ##__VA_ARGS__ in my variadic macros (i.e., __VA_ARGS__ preceded by two # symbols) and it seems to be working with -std=gnu99. Do you foresee any problems with this combo? (I'm just a C student at the moment and have yet to run into cross-compiler issues.) – iceman Oct 12 '14 at 00:07
  • I'm biassed, but I suggest looking at [C `#define` macro for debug printing](http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing/1644898#1644898) for ideas on how to implement debugging macros better. In particular, it is bad idea to have the compiler completely ignore the debugging macros when the debugging is disabled. You want it to check the code for validity so that when you re-enable the debugging, it is still valid. – Jonathan Leffler Oct 12 '14 at 01:21
  • @DipakC: Actually in my comment above the second `#` is missing, it should be `##__VA_ARGS__`. I don't see a problem with this practice except that you require GCC for this. However when you're doing preprocessor black magic already, you can also detect the compiler with that, and define the macros appropriately. All of my stuff written in C usually contains a header `_compiler.h` where all the black magic goes. – datenwolf Oct 12 '14 at 09:46

1 Answers1

2

The proeprocessor, just like the C compiler, scans files from top to bottom. That means macros must be defined before they are used.

So to solve your problem, put the #define before the #include.

#include <stdio.h>

#define KRYPTONITE

#include "test.h"

int main (int argc, char *argv[])
{
  printf("\nSuperman, are you here?\n\n");
  superman("I'm here");  // Doesn't print
  return 0;
}
Vilx-
  • 104,512
  • 87
  • 279
  • 422
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621