|Fundamental C - Compilation & Preprocessor|
|Written by Harry Fairhead|
|Monday, 17 February 2020|
Page 3 of 3
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:
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.
#if ARM int processor=1; #else int processor=2; #endif
If you have defined the macro ARM then the source file contains the line:
if the macro isn’t defined then the source file contains the line:
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:
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.
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.
#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.
Fundamental C: Getting Closer To The Machine
Now available as a paperback and ebook from Amazon.
Also see the companion volume: Applying C
or email your comment to: firstname.lastname@example.org
|Last Updated ( Monday, 17 February 2020 )|