#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. #define
s 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 ifdef
ing 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
Base Pointer to Array of Derived Objects
Qt3D. Draw Transparent Qspheremesh Over Triangles
Ostream Chaining, Output Order
Array Decay to Pointers in Templates
C++ Delete Pointer Issue, Can Still Access Data
How to Deal with Global-Constructor Warning in Clang
Overriding Static Variables When Subclassing
What Is C++ Version of Realloc(), to Allocate the New Buffer and Copy the Contents from the Old One
Can Raw Pointers Be Used Instead of Iterators with Stl Algorithms for Containers with Linear Storage
Is the Behavior of Subtracting Two Null Pointers Defined
Cmake: Failed to Run Msbuild Command: Msbuild.Exe
Set All Bytes of Int to (Unsigned Char)0, Guaranteed to Represent Zero