The magic of #ifdef
The beauty of the preprocessor #ifdef . . . #endif directives in C and C++ is that there are so many ways to abuse them.
I’ve been working on some vintage code (at least 15 years old) that provides a model for how not to do things. The compilation is controlled by no fewer than 750 #ifdef switches. Many of these are used in header files as guards against double inclusion, but the others roughly split into these jobs:
- controlling platform-specific code generation
- controlling project-specific code generation
- experimental features
- controlling different versions of hardware
The oddest of these switches are:
For the people who don’t like to document:
#ifdef __
For dyslexic programmers:
#ifdef DSTL_UPGRADES #ifdef DTSL_UPGRADES
For those who think the code runs too quickly:
#ifdef INEFFICIENT
For those hopeful of a quick fix:
#ifdef MAKETHISWORK
For those who aren’t confident of our source control systems (and are dyslexic):
#ifdef OLD_SLOW_WAY #ifdef ORIGINAL_CODE #ifdef OROGINAL_CODE #ifdef REDUNDANT_CODE #ifdef REDUNDANT_FUNCTIONS
For those who can’t quite remember which operating system they are using:
#ifdef _vxworks #ifdef __vxworks #ifdef VXWORKS #ifdef _VXWORKS #ifdef __VXWORKS
For those trying the super-secret go-faster-stripes:
#ifdef WIN32_LEAN_AND_MEAN
For those who super unpositively don’t no way double negative want that code:
#ifdef _WIN32_trynot
. . . but just the once, or later, or huh, maybe not at all?:
#ifdef __JUSTONCE__ #ifdef _JUST_ONCE_ #ifdef notdef #ifdef __NOTSMART_ #ifdef _NOTSMART_ #ifdef notyet #ifdef NOTYET #ifdef THIS_IS_NECESSARY #ifdef THIS_IS_TOO_EXPENSIVE
Even the choice of names for include guards shows how coding standards change over time, or are ignored, or how the language standards themselves are ignored (the leading underscores):
xxx_inc_ _xxx_H_ __xxx_H__ xxx_include xxx_H xxx_inc xxx_h xxx_Hinc _INC_xxx INC_xxx