Fundamental C - Compilation & Preprocessor
Written by Harry Fairhead   
Monday, 17 February 2020
Article Index
Fundamental C - Compilation & Preprocessor
Macros
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
text
#endif

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:

#else

and

#elif

to create the familiar conditional structures.

For example:

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

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
#endif

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:

defined(MACRO)

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
#endif

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

Summary

  • 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

<ASIN:1871962609>

<ASIN:1871962463>

<ASIN:1871962617>

<ASIN:1871962455>

 

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.

Banner


Sequin - Open Source Message Stream Built On Postgres
31/10/2024

Sequin is a tool for capturing changes and streaming data out of your Postgres database, guaranteeing exactly once processing. What does that mean?



JetBrains Improves Kubernetes Support In IDE Upgrades
12/11/2024

JetBrains has improved its IDEs with features to suggest the logical structure of code, to streamline the debugging experience for Kubernetes applications, and provide comprehensive cluster-wide Kuber [ ... ]


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Monday, 17 February 2020 )