Fundamental C - Compilation & Preprocessor
Written by Harry Fairhead   
Monday, 17 February 2020
Article Index
Fundamental C - Compilation & Preprocessor
Conditional Compilation

Conditional Compilation

The preprocessor has another major use in addition to includes and macros – conditional compilation, which enables a number of conditional directives to be evaluated at compile time.

The most basic of these are:

#ifdef MACRO

If the macro is defined then all of the text between the ifdef and endif is included in the output file. If the macro isn’t defined than the text is skipped. The text can even contain macros and these will be expanded if text is included. Also notice that text has to expand to valid C.

There is also:

#ifndef MACRO

which works in the same way but text is included if the macro isn’t defined.

You can also use:




to create the familiar conditional structures.

For example:

#if ARM
int processor=1;
int processor=2;

If you have defined the macro ARM then the source file contains the line:

int processor=1;

if the macro isn’t defined then the source file contains the line:

int processor=2;

The only difficulty is in keeping in mind that all of these conditionals are evaluated when the preprocessor runs, i.e. before the compiler, and that they are all text modifications.

A very common use of conditional compilation is to make sure that a header file is only actually included once, no matter how many times the programmer includes it:

#ifndef MYHEADER
#define MYHEADER
text of header file

The first time the header file is included, MYHEADER is not defined so the whole text of the header file is added to the source code. The second and subsequent times the header is included, MYHEADER is defined and so its text is not added to the source code.

Most of the time you can rely on just using #ifdef but there is a more sophisticated conditional:

#if expression

where expression is an integer C expression with some restrictions. You can use addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations, but only with integer and character constants – the value of any variable that you use obviously cannot be known until runtime. If you do use an identifier that isn’t a macro then it is treated as zero. You can also use macros within the expression and these will be expanded before the expression is evaluated.

The operator:


is useful in that it is true, i.e. 1, if MACRO is defined.

One of the main uses of #if is to test for combinations of macros to be defined.

For example:

#if defined(ARM) && defined(BIGRAM)

will only include its text if both ARM and BIGRAM are defined.

You can see that conditional compilation is useful when you need to tailor your code to different systems, but it can also be useful if you want to include optional features, e.g. debugging code.

Another common use of conditional compilation is to comment out a block of code. You might think that surrounding the code by /* */ would do the job, but any block comments within the code being commented out would cancel the outer comment as comments don’t nest. A simple solution is to surround the block with:

#if 0
text to be removed

This is safer than using ifdef as the macro might be undefined by another part of the program. Notice that this also works if the text contains conditionals as it isn’t included and hence never expanded or processed.

Included in the chapter but not in this extract.

  • Linking
  • A Static Library
  • Creating a Dynamic Library
  • Make
  • Conclusion


  • When you compile a C program there are four distinct stages: Preprocessing, Compilation, Assembly and Linking.

  • The C preprocessor can be used to modify C source code using macros. It is important to keep in mind that everything that the preprocessor does is about text manipulation.

  • The include command can be used to read in files into the compilation unit.

  • More generally macros can be used to define constants and implement conditional compilation.

  • Linking is the process whereby any unresolved function calls are resolved by loading code from libraries.

  • Library files come in two forms – static and dynamic.

  • A static library contains functions which are added to your code as needed. This means that your code contains a copy of the function and this can make its executable larger than necessary.

  • A dynamic library is shared among all the programs that use it. This saves storage, but the executable has to be able to find the library when it runs. There is also the problem of updates to shared library files breaking the programs that make use of them.

  • Make is a batch file processor that makes compiling more efficient by only processing those files that have changed since the last time the program was compiled.


Fundamental C: Getting Closer To The Machine

Now available as a paperback and ebook from Amazon.

  1. About C
      Extract Dependent v Independent
                  & Undefined Behavio
  2. Getting Started With C Using NetBeans
  3. Control Structures and Data
  4. Variables
      Extract Variables 
  5. Arithmetic  and Representation
      Extract Arithmetic and Representation 
  6. Operators and Expression
      Extract: Expressions
      Extract Side Effects, Sequence Points And Lazy Evaluation
      First Draft of Chapter: Low Down Data
  7. Functions Scope and Lifetime
  8. Arrays
      Extract  Simple Arrays 
      Extract  Ennumerations 
  9. Strings
      Extract  Simple Strings
    Extract: String I/O ***NEW!!
  10. Pointers
      Extract  Starting Pointers
      Extract  Pointers, Cast & Type Punning
  11. Structs
      Extract Basic Structs 
      Extract Typedef
  12. Bit Manipulation
      Extract Basic Bits
      Extract Shifts And Rotates 
  13. Files
     Extract Files
    Extract Random Access Files 
  14. Compiling C – Preprocessor, Compiler, Linker
     Extract Compilation & Preprocessor

Also see the companion volume: Applying C






Harry Fairhead is the author of Raspberry Pi IoT in C ,  Micro:bit IoT in C and Fundamental C: Getting Closer to the Machine. His latest book is  Applying C For The IoT With Linux.

Related Articles

Remote C/C++ Development With NetBeans

Raspberry Pi And The IoT In C

Getting Started With C/C++ On The Micro:bit

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.


GitHub Grows As Business and Open Source Establish Firm Ties

Today sees the start of Universe2022, GitHub's global developer event which is now in its seventh year. With it comes the 10th annual Octoverse report which gives details of the latest state of o [ ... ]

Visual Studio Code Now Supports Virtual Threads

The recently released Java 19 comes with the JEP 425 preview of Virtual Threads as part of Project Loom. VSCode was quick to adapt it.

More News





or email your comment to:

Last Updated ( Monday, 17 February 2020 )