C preprocessor: Difference between revisions
[unchecked revision] | [unchecked revision] |
Content deleted Content added
Unstubbed predefined tokens and added some information. |
m Bot: Replace deprecated source tag with syntaxhighlight |
||
(3 intermediate revisions by 3 users not shown) | |||
Line 9:
The most familiar use of the preprocessor is to include header files (containing function declarations, definition of constants etc.):
<
#include <stdio.h>
#include "myheader.h"
</syntaxhighlight>
The effect is that the contents of the given header file are pasted into the source file. The ''technical'' difference between <> and "" is that the compiler is allowed to satisfy <> includes internally, i.e. without actually accessing any on-disk files of that name. None of the prominent compilers do this, to the knowledge of the author, but it has become common practice to use <> for system headers and "" for your own header files.
Line 25:
The preprocessor can ''define'' tokens. It is good custom to write these tokens in ALL CAPS. (See pt. 2 as for why.)
<
#define MYTOKEN
</syntaxhighlight>
Most compilers also allow the definition of preprocessor tokens on the command line, e.g. the "-D MYTOKEN" option for [[GCC]].
Line 34:
The preprocessor can ''conditionally'' select which parts of source code to compile, depending on whether a given token is defined or not (see above).
<
#define MYTOKEN
Line 46:
/* This source will be compiled */
#endif
</syntaxhighlight>
Note that such ''#if'' / ''#ifdef'' / ''#ifndef'' - ''#endif'' sections can be nested.
Line 55:
The solution are ''header guards'', a combination of conditional compilation and token definition:
<
/* abc.h */
Line 64:
#endif
</syntaxhighlight>
== Preprocessor Macros, pt. 2 ==
Line 73:
The ''#if'' statement can be used to base conditional compilation on token values. Note that the preprocessor can only work with compile-time constants. Compiler-evaluated code like `sizeof()` cannot be used in preprocessor directives. On the upside, the preprocessor can natively handle non-numerical values.
<
#define MYTOKEN foo
#define OTHERTOKEN 42
Line 90:
/* Won't be compiled. */
#endif
</syntaxhighlight>
The ''#if'' directive also allows for a simple construct to disable a region of code without having to worry about nested ''/* ... */'' style comments:
<
#if 0
/* disabled code */
#endif
</syntaxhighlight>
Such code can easily be re-enabled temporarily with no more effort than replacing the "0" with a "1". Source comments as to why you disabled code this way are in order.
Line 134:
Assertions are used to catch situations which should never happen, even under error circumstances. If the condition given in the parantheses does not evaluate to "true", a diagnosis is printed which contains source file name, line number, and (since C99) name of the current function; the program then calls abort().
<
#include <assert.h>
Line 140:
assert( 1 != 2 );
assert( gdt_ptr != null );
</syntaxhighlight>
For production code, assertions may be turned off by defining NDEBUG:
<
gcc -DNDEBUG ...
</syntaxhighlight>
Note that <assert.h> does not have (or need) a header guard, i.e. can be included multiple times in a source file, and that whether NDEBUG is defined or not is evaluated anew ''at every inclusion of <assert.h>''. You can thus enable / disable assertions at a very fine-grained level if necessary:
<
#include <assert.h>
Line 171:
#include <assert.h>
#endif
</syntaxhighlight>
== See also ==
=== Articles ===
* [[C]]
* [[Why function implementations shouldn't be put In header files]]
=== External Links ===
Line 183 ⟶ 184:
[[Category:C]]
[[Category:Tutorials]]
|