I have code that I want to have two modes, debug and verbose. I define them in my header file as,
#define verbose TRUE
#def
If we rack our brains enough, we can come up with a difference. But it is obscure and involves undefined behavior, so it is of no consequence if all we care about is whether the code is strictly conforming to ISO C.
The #if defined ...
form is susceptible to behaving differently if previously a #define defined ...
macro was processed. In the ISO C99 standard it was written, in regard to the #if
and #elif
directives:
Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the controlling constant expression are replaced (except for those macro names modified by the defined unary operator), just as in normal text.
No requirement is given that the defined
unary operator be recognized and protected from being treated as a macro; it is just one of the "preprocessing tokens that will become the ... expression". The defined
operator is recognized at this stage only for the purposes of protecting its argument from expansion.
If the definition of define
as a macro is simply permitted to stand, and occurrences of defined
are subsequently replaced (including in the arguments of #if
preprocessing directives) thus interfering with #if defined
, while not affecting #ifdef
.
Perhaps this area of the language was tightened up since C99.
#if defined(MACRO)
is the same as #ifdef MACRO
, but is longer. On the other hand it allows to add extra conditions with ||
or &&
.
#if MACRO
is similar to #ifdef MACRO
but not 100%. If MACRO
is 0
then #if MACRO
will be negative - it requires MACRO
to be defined and not be 0
. #ifdef
checks only whether it is defined even without value (#define MACRO
).
Now is modern to use #if
and enable/disable definitions with value 1 or 0:
#define FLAG_X 1 // or 0
If I'm reading your question correctly the title is misleading, it should be
Is #if MACRO equivalent to #ifdef MACRO?
They are not equivalent but they can (and often are) both used to specify binary modes which are either on or off. The choice is, in my opinion, a matter of personal preference.
You are using the first option and either have
#define verbose true
or
#define verbose false
and then check the mode using either
#if verbose
or
#if !verbose
Actually, I would recommend you use either TRUE or 1 instead of true and either FALSE or 0 instead of false, because true and false, are (or can be) C/C++ values and the pre-processor doesn't have access to C/C++ values.
Anyway, the other common way to specify binary modes is to either define the flag or leave it undefined in which case you can have either
#define verbose any thing (including nothing) goes here
or leave out the #define.
and then you can test whether the flag is defined, either with
#ifdef verbose
or its equivalent
#if defined(verbose)
NOTE: In this case, you are not testing the value of the flag you only need to test whether it is defined.
If it is more convenient you can also test whether the flag is undefined with either
#ifndef verbose
or its equivalent
#if !defined(verbose)
No, they are not at all equivalent. An #if MACRO
branch is compiled if MACRO
evaluates to non-zero. On the other hand, an #ifdef MACRO
branch is compiled if MACRO
is defined, no matter what it evaluates to. So
#include <stdio.h>
#define VAR_SET_TO_TRUE 1
#define VAR_SET_TO_FALSE 0
int main()
{
#if VAR_SET_TO_TRUE
printf("#if VAR_SET_TO_TRUE\n");
#endif
#if VAR_SET_TO_FALSE
printf("#if VAR_SET_TO_FALSE\n");
#endif
#if VAR_UNSET
printf("#if VAR_UNSET\n");
#endif
#ifdef VAR_SET_TO_TRUE
printf("#ifdef VAR_SET_TO_TRUE\n");
#endif
#ifdef VAR_SET_TO_FALSE
printf("#ifdef VAR_SET_TO_FALSE\n");
#endif
#ifdef VAR_UNSET
printf("#ifdef VAR_UNSET\n");
#endif
}
will output
#if VAR_SET_TO_TRUE
#ifdef VAR_SET_TO_TRUE
#ifdef VAR_SET_TO_FALSE
Note that the line printf("#ifdef VAR_SET_TO_FALSE\n");
is compiled while the line printf("#if VAR_SET_TO_FALSE\n");
is not. The first one is compiled, because VAR_SET_TO_FALSE
is defined, even though its value is false
.
#ifdef MACRO
#if defined (MACRO)
will do the exact same thing. However, the defined (MACRO) is just an expression that evaluates to 0 or 1 inside the #if, and it can be combined with other expressions. For example
#if defined (MACRO) && ! defined (MACRO2)
// Do this
#else
// Do that
#endif
Try doing that with #ifdef - you can't unless your code gets really clumsy.