0

I am confused about the if statement in macro. Here is my code:

#ifdef SHOW_LOGS_
#define LOG(operation, parameter, value) \
do { \
    if ((parameter) == (NULL)){ \
        fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,operation);\
    }else { \
        fprintf(stderr,"%s:%d: %s, [%s] : %d\n",__FILE__,__LINE__,operation,parameter,value);\
    } \
} while(0)
#else
#define LOG 
#endif

But, when I test my code like:

LOG("ROUNDING UP...",NULL,NULL);

The compiler gave me a warning, which tells me that the test code above turn to execute

fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,operation);

not the right one. So the if statement didn't work.

And here is another example:

#define TEST_EQ_BASE(equality,expect,actual,format) \
    do {    \
        test_count++;   \
        if (equality){  \
            test_pass++;\
        }else{  \
            main_ret = 1;   \
            fprintf(stderr,"%s:%d: expect: " format " actual: " format "\n",__FILE__,__LINE__,expect,actual);\
        }   \
    }while (0)

In this code, the if statement works.

I am very confused about it, why is the difference?

Thank you!

Edit:

Sorry you guys, I am a junior student, not so familiar with the macro, so sorry.

I checked the result, the if statement did worked, but the compiler still complains:

uninitialized.h:88:2: note: in expansion of macro ‘LOG’
  LOG("__uninitialized_copy_aux: copying without constructor...",NULL,NULL);
  ^
stl_config.h:53:87: warning: format ‘%d’ expects argument of type ‘int’, but argument 7 has type ‘long int’ [-Wformat=]
    fprintf(stderr,"%s:%d: %s, [%s] : %d\n",__FILE__,__LINE__,operation,parameter,value);\

This is the output:

uninitialized.h:88: __uninitialized_copy_aux: copying without constructor...

This is the macro expanded:

do { if ((__null) == (__null))
{ fprintf(stderr,"%s:%d: %s, [%s] : %d\n","uninitialized.h",80,"__uninitialized_copy_aux: copying with constructor...",__null,__null); }else 
{ fprintf(stderr,"%s:%d: %s\n","uninitialized.h",80,"__uninitialized_copy_aux: copying with constructor..."); } } while(0);

So I think the problem is when passing NULL to the macro, the compiler gives the warning, can I eliminate the warning?

Thank you!!

Jiahao Cai
  • 1,222
  • 1
  • 11
  • 25
  • First of all, don't create your own symbols with leading underscore followed by another underscore or by an upper-case letter, [those are reserved](http://stackoverflow.com/a/228797/440558). Secondly, have you tried running only the preprocessor to see what the macro invocation expands to? – Some programmer dude Jan 06 '17 at 06:36
  • `if ((parameter) == (NULL))`, your `parameter` is `NULL`, what is your problem? – Danh Jan 06 '17 at 06:37
  • Also please show us the *exact* warning the compiler gives you, verbatim, complete and unedited. – Some programmer dude Jan 06 '17 at 06:38
  • Anyway, type of `NULL` is unspecified, `%s` need a `char*` or `const char*` – Danh Jan 06 '17 at 06:40
  • 2
    Should the comparison not be `(parameter) != NULL`, anyway? – Rene Jan 06 '17 at 06:42
  • Please add the warning to the Q. However, as said by @Rene you have to negate the condition to make it semantically useful. – Amin Negm-Awad Jan 06 '17 at 06:49
  • You should cast each parameter you pass to `fprintf` from a macro, since the compiler has no way to know what the parameter types are. (Or better yet, call your own function that has well-defined types rather than using `...`.) – David Schwartz Jan 06 '17 at 07:23
  • You probably need to rethink the `#define` in your `#else` clause. If you do not have `SHOW_LOGS_` defined, your invocation `LOG("ROUNDING UP...",NULL,NULL);` becomes `("ROUNDING UP...",NULL,NULL);` which is a parenthesized statement expression featuring the comma operator . Often, you end up with `#define LOG(operation, parameter, value) ((void)0)`. There are merits to evaluating the parameters — you'd probably want to use `#define LOG(operation, parameter, value) ((void)((operation), (parameter), (value)))` or thereabouts to ensure that the value is discarded. – Jonathan Leffler Jan 06 '17 at 07:32
  • See also [C `#define` macro for debug printing](http://stackoverflow.com/questions/1644868). – Jonathan Leffler Jan 06 '17 at 07:33
  • an obvious solution is `LOG("ROUNDING UP...",NULL,0);` . The last argument is printed with `%d` so it should have type `int` – M.M Jan 06 '17 at 08:45

1 Answers1

2

Please look at your code again.

#define LOG(operation, parameter, value) \
do { \
    if ((parameter) == (NULL)){ \
        fprintf(stderr,"%s:%d: %s, [%s] : %d\n",__FILE__,__LINE__,operation,parameter,value);\
    }else { \
        fprintf(stderr,"%s:%d: %s\n",__FILE__,__LINE__,operation);\
    } \
} while(0)

Are you really going to fprintf the parameter if (parameter) == (NULL) ?

Try change this line

if ((parameter) == (NULL)){ \

to

if ((parameter)){ \
raymai97
  • 806
  • 7
  • 19