C preprocessor: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(New intro.)
Line 1: Line 1:
{{Disputed|C preprocessor}}
== C preprocessor ==
== C preprocessor ==

The C preprocessor is a powerful tool and properly used may be very useful.
The C preprocessor is the first step in the process of translating C/C++ source code into a binary (preprocessing -> compiling -> linking). In trivial environments, the preprocessor is used only for '''#include'''ing header files, and providing "header guards" to avoid multiple inclusions.
The following have been checked to work in GCC.

But the preprocessor can do much more, and can be very useful - not only for C/C++ sources, but for your Assembler sources just as well.

It should be used with care and moderation though, because it can also obfuscate your source code and introduce bugs that are very difficult to debug.


=== Rules ===
=== Rules ===

<source lang="c">
<source lang="c">
#ifdef SOME_MACRO
#ifdef SOME_MACRO
Line 24: Line 28:
that the preprocessor can be used with languages other than C. The standard way to invoke the preprocessor with GCC is "gcc -E".
that the preprocessor can be used with languages other than C. The standard way to invoke the preprocessor with GCC is "gcc -E".
{{stub}}
{{stub}}

=== Uses ===
=== Uses ===



Revision as of 09:04, 30 June 2010

C preprocessor

The C preprocessor is the first step in the process of translating C/C++ source code into a binary (preprocessing -> compiling -> linking). In trivial environments, the preprocessor is used only for #includeing header files, and providing "header guards" to avoid multiple inclusions.

But the preprocessor can do much more, and can be very useful - not only for C/C++ sources, but for your Assembler sources just as well.

It should be used with care and moderation though, because it can also obfuscate your source code and introduce bugs that are very difficult to debug.

Rules

#ifdef SOME_MACRO
#define SOME_OTHER_MACRO SOME_VALUE
#undef SOME_MACRO
#endif

#ifndef NDEBUG
/* Older compilers may not have __func__ */
fprintf(stderr, __FILE__ ":" __LINE__ " : in function " __func__ "\n");
#endif

The preprocessor can be used to define macros with the #define macro. A previously defined macro can be undefined with #undef. And #ifdef block can be used to conditionally compile a block of code if a certain macro is defined. This can be useful if the code is platform-dependant, or is used for debugging.

When the preprocessor reads a file, it replaces any occurrence of a defined macro with the value it was defined to. Since the preprocessor is language agnostic, if an error is introduced through its use, the error will not be reported until the file is compiled. This also means that the preprocessor can be used with languages other than C. The standard way to invoke the preprocessor with GCC is "gcc -E".

This page is a stub.
You can help the wiki by accurately adding more contents to it.

Uses

assert()

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>

assert( sizeof(struct free_memory_block) == 8 );
assert( 1 != 2 );
assert( gdt_ptr != null );

For production code, assertions may be turned off by defining NDEBUG:

gcc -DNDEBUG ...

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>

    /* assert() at this point only fails-on-false if NDEBUG is not defined */
    assert( isChecksumCorrect() );

#ifdef NDEBUG
/* Hard-enabling of assert() even if NDEBUG is defined */
#define NDEBUG_WAS_SET
#undef NDEBUG
#include <assert.h>
#endif

    /* assert() in this block of code should fail-on-false even in production */
    assert( isChecksumCorrect() );

#ifdef NDEBUG_WAS_SET
/* Restoring NDEBUG if it was enabled originally */
#define NDEBUG
#include <assert.h>
#endif

Disabled Code

Sometimes you want to disable a section of code. However, if the code already contains /* C-style comments */, using those very same comments is not an option because they do not nest. The preprocessor provides an easy way around:

#if 0
    /* disabled code */
    ...
#endif

If you want to enable the code section only temporarily, replace the '#if 0' with '#if 1'. Using '#else' it is even possible to have alternative code sections (e.g. for testing).

Hazards of the C preprocessor

There is a number of counter-intuitive consequences of macros and macro expanding design. Macro Pitfalls

See also

External Links

The GNU C preprocessor manual: