#Ifdef VS #If - Which Is Better/Safer as a Method for Enabling/Disabling Compilation of Particular Sections of Code

#ifdef vs #if - which is better/safer as a method for enabling/disabling compilation of particular sections of code?

My initial reaction was #ifdef, of course, but I think #if actually has some significant advantages for this - here's why:

First, you can use DEBUG_ENABLED in preprocessor and compiled tests. Example - Often, I want longer timeouts when debug is enabled, so using #if, I can write this

  DoSomethingSlowWithTimeout(DEBUG_ENABLED? 5000 : 1000);

... instead of ...

#ifdef DEBUG_MODE
DoSomethingSlowWithTimeout(5000);
#else
DoSomethingSlowWithTimeout(1000);
#endif

Second, you're in a better position if you want to migrate from a #define to a global constant. #defines are usually frowned on by most C++ programmers.

And, Third, you say you've a divide in your team. My guess is this means different members have already adopted different approaches, and you need to standardise. Ruling that #if is the preferred choice means that code using #ifdef will compile -and run- even when DEBUG_ENABLED is false. And it's much easier to track down and remove debug output that is produced when it shouldn't be than vice-versa.

Oh, and a minor readability point. You should be able to use true/false rather than 0/1 in your #define, and because the value is a single lexical token, it's the one time you don't need parentheses around it.

#define DEBUG_ENABLED true

instead of

#define DEBUG_ENABLED (1)

How to avoid specific #ifdef in multi - platform qt code?

You can create separate EventListener.cpp files for windows and unix and put these files into subdirectories like (win, linux). To the makefile or to the projectfile you can add one implementation file based on the current platform. The compiler will compile just one file for the current platform.

With this method you can avoid ifdefing totally.

If the definitions are different you can use pImpl idiom to separate the implementation details of a class: https://cpppatterns.com/patterns/pimpl.html

Generate #ifdef, #endif clause with another macro

If, instead of not defining HAVE_FOO, you define it to 0, you can do:

const struct {
bool present;
const char *name;
} features[NFEATURES] = {
{HAVE_FOO, "foo"},
{HAVE_BAR, "bar"},
...
};

for (size_t i=0; i < NFEATURES; i++)
if (features[i].present)
printf(" ... and we've got: %s\n", features[i].name);

You'll have to check for #if HAVE_FOO instead of #ifdef HAVE_FOO then, and your --help message may be displayed a bit slower if your number of features runs in the zillions (in which case I'd recommend a different architecture anyway).

Program compiled on Linux not getting code in #ifdef section

Your make file actually does work for c files, but not for c++ files.

This is because you invoke your custom compile command line for c compilation but your cpp files are going directly into what is effectively your link command line which does not specify compilation flags.

Is this a valid C ifdef structure? Is there a better way?

#ifdef FILE_FORMAT_TWO
sprintf(xxx);
#elif defined(NEW_FILE_FORMAT)
sprintf(xxx);
#else
sprintf(xxx);
#endif

And here is an explanation. The C pre-processor directives permit you to use #ifdef as a shortform for #if defined. The Gnu C compiler's pre-processor directives can be found here. That document is somewhat long, so the portion that pertains to conditional syntax lies here.

In general though, I've found it cleaner to be explicit in my pre-processing directives, like so:

#if defined(FILE_FORMAT_TWO)
sprintf(xxx);
#elif defined(NEW_FILE_FORMAT)
sprintf(xxx);
#elif defined(DEFAULT_FILE_FORMAT)
sprintf(xxx);
#else
#error "You must define blah blah"
#endif

Credits to Jonathan Leffler for pointing out the stylistic inconsistency in #ifdef FILE_FORMAT_TWO and suggesting replacement with #if defined (FILE_FORMAT_TWO)

What use cases necessitate #define without a token-string?

This is used in two cases. The first and most frequent involves
conditional compilation:

#ifndef XYZ
#define XYZ
// ...
#endif

You've surely used this yourself for include guards, but it can also be
used for things like system dependencies:

#ifdef WIN32
// Windows specific code here...
#endif

(In this case, WIN32 is more likely defined on the command line, but it
could also be defined in a "config.hpp" file.) This would normally
only involve object-like macros (without an argument list or
parentheses).

The second would be a result of conditional compilation. Something
like:

#ifdef DEBUG
#define TEST(X) text(X)
#else
#define TEST(X)
#endif

That allows writing things like:

TEST(X);

which will call the function if DEBUG is defined, and do nothing if it
isn't.

Computed Includes in C

There's some other places in the code or build system that define or don't define the macros that are being tested in the conditionals. What's suggested is that instead of those places defining lots of different SYSTEM_1, SYSTEM_2, etc. macros, they'll just define SYSTEM_H to the value that's desired.

Most likely this won't actually be in an explicit #define, instead of will be in a compiler option, e.g.

gcc -DSYSTEM_H='"system_1.h"' ...

And this will most likely actually come from a setting in a makefile or other configuration file.

Simple ways to disable parts of code

I'm not sure I should post this because it's not something I think is 'good code', but I'll admit to having used the following technique as a quick-n-dirty way to be able to quickly switch between two small snippets of code when I'm just checking something out:

// in the following , foo() is active:
/**/ foo(); /*/ bar(); /**/

Now just remove one of the asterisks at the front:

// now bar() is active:
/*/ foo(); /*/ bar(); /**/

Of course, this should never make it past the "just checking things out" phase...



Related Topics



Leave a reply



Submit