28

I have code that I want to have two modes, debug and verbose. I define them in my header file as,

#define verbose TRUE
#define debug TRUE

In my code so far, I have just been using

#if(debug)
  //code
#endif

but is it more proper to use?

#ifdef debug
  // code
#endif

I read something about preprocessor macros but it didn't make sense at the time. So, I have a question: Is #if defined MACRO equivalent to #ifdef MACRO? and which one is better for enabling/disabling a particular section of code?

Milan
  • 1,743
  • 2
  • 13
  • 36
msc
  • 33,420
  • 29
  • 119
  • 214
  • 10
    This seems to be comparing `#ifdef` with `if`, not with `#if defined` as the title suggests. – Oliver Charlesworth Sep 02 '16 at 10:21
  • 5
    The difference between the two is that `#ifdef` can only use a single condition, while `#if defined(NAME)` can do compound conditionals. – LPs Sep 02 '16 at 10:23
  • 3
    BTW, after edit, your code is different: `#if` debug checks if `debug` is true while `#ifdef` checks only if `debug` is defined. – LPs Sep 02 '16 at 10:28
  • unclear question: please decide whether you are comparing `#ifdef` with `#if defined` as in the title; or whether you are comparing `#if debug` with `#ifdef debug` as in your code sample – M.M Sep 03 '16 at 04:37
  • @M.M I did a correction. – msc Sep 03 '16 at 04:49
  • See also: http://stackoverflow.com/questions/1714245/difference-between-if-definedwin32-and-ifdefwin32 – Pang Sep 06 '16 at 07:00
  • Does this answer your question? [difference between #if defined(WIN32) and #ifdef(WIN32)](https://stackoverflow.com/questions/1714245/difference-between-if-definedwin32-and-ifdefwin32) – Grant Jun 12 '20 at 18:40

5 Answers5

36
#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.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • 7
    `defined` doesn't require parentheses. It has two forms: `defined (identifier)` and `defined identifier`. – Kaz Sep 02 '16 at 14:10
9

#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

i486
  • 6,491
  • 4
  • 24
  • 41
8

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.

Dreamer
  • 1,139
  • 9
  • 18
  • 1
    The OP is asking about the difference between `#ifdef` and `#if defined` not the difference between `#if` and `#if defined` - perhaps you might adapt your answer to that case. Also from memory `#if` clauses are executed if the RHS evaluates to non-zero, not to 1. – abligh Sep 02 '16 at 16:35
3

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)
Stuart
  • 1,428
  • 11
  • 20
  • [TO OP]Misleading title: please fix. This will make the other answers invalid, but you should do it. – EKons Sep 02 '16 at 14:53
2

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.

Kaz
  • 55,781
  • 9
  • 100
  • 149