Understanding Preprocessor Directives & Macros in C Programming, Study notes of Windows Programming

An overview of preprocessor directives in c programming, focusing on the usage of #ifdef, #ifndef, #include, and macros. Preprocessor directives are instructions given to the compiler before the actual compilation process. They allow for conditional compilation, inclusion of header files, and definition of constants. #ifdef and #ifndef are used to test if a preprocessor variable has been defined, preventing multiple definitions in header files. #include instructs the compiler to read another source file. Macros are fragments of code given a name, increasing code speed at the cost of program size.

Typology: Study notes

2011/2012

Uploaded on 08/07/2012

anishay
anishay 🇮🇳

4.2

(25)

118 documents

1 / 7

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Preprocessor Directives 2
Preprocessor
The preprocessor is a program that runs prior to compilation and potentially modifies a
source code file. It may add code in response to the #include directive, conditionally
include code in response to #if, #ifdef, #ifndef directives or define constants using the
#define directive.
As defined by the ANSI standard, the C preprocessor contains the following directives:
#if #ifdef #ifndef #else #elif #include #define #undef #line #error #pragma
Preprocessor directives: #ifdef and #ifndef
The #ifdef (if defined) and #ifndef (if not defined) preprocessor commands are used to
test if a preprocessor variable has been "defined".
Prevent multiple definitions in header files
When there are definitions in a header file that can not be made twice, the code below
should be used. A header file may be included twice because more than one other
“include file” includes it, or an included file includes it and the source file includes it
again.
To prevent bad effects from a double include, it is common to surround the body in the
include file with the following:
#ifndef MYHEADERFILE_H
#define MYHEADERFILE_H
. . . // This will be seen by the compiler only once
#endif /* MYHEADERFILE_H */
Turning debugging code off and on
Debugging code is necessary in programs; however, it is not usually appropriate to leave
it in the delivered code. The preprocessor #ifdef command can surround the debugging
code. If DEBUG is defined as below (probably in an include file) all debugging statement
surrounded by the #ifdef DEBUG statement will be active. However, if it isn't defined,
none of the statements will make it through the preprocessor.
#define DEBUG
. . .
#ifdef DEBUG
. . . // debugging output
#endif
docsity.com
pf3
pf4
pf5

Partial preview of the text

Download Understanding Preprocessor Directives & Macros in C Programming and more Study notes Windows Programming in PDF only on Docsity!

Preprocessor

The preprocessor is a program that runs prior to compilation and potentially modifies a source code file. It may add code in response to the #include directive, conditionally include code in response to #if, #ifdef, #ifndef directives or define constants using the #define directive. As defined by the ANSI standard, the C preprocessor contains the following directives:

#if #ifdef #ifndef #else #elif #include #define #undef #line #error #pragma

Preprocessor directives: #ifdef and #ifndef

The #ifdef (if defined) and #ifndef (if not defined) preprocessor commands are used to test if a preprocessor variable has been "defined".

Prevent multiple definitions in header files

When there are definitions in a header file that can not be made twice, the code below should be used. A header file may be included twice because more than one other “include file” includes it, or an included file includes it and the source file includes it again.

To prevent bad effects from a double include, it is common to surround the body in the include file with the following:

#ifndef MYHEADERFILE_H #define MYHEADERFILE_H

... // This will be seen by the compiler only once #endif / MYHEADERFILE_H /

Turning debugging code off and on

Debugging code is necessary in programs; however, it is not usually appropriate to leave it in the delivered code. The preprocessor #ifdef command can surround the debugging code. If DEBUG is defined as below (probably in an include file) all debugging statement surrounded by the #ifdef DEBUG statement will be active. However, if it isn't defined, none of the statements will make it through the preprocessor.

#define DEBUG

... #ifdef DEBUG ... // debugging output #endif

Some Preprocessor directives

  • #define

#define defines an identifier (the macro name) and a string (the macro substitution) which will be substituted for the identifier each time the identifier is encountered in the source file. Once a macro name has been defined, it may be used as part of the definition of other macro names.

If the string is longer than one line, it may be continued by placing a backslash on the end of the first line. By convention, C programmers use uppercase for defined identifiers.

Example: macro #defines

#define TRUE 1 #define FALSE 0

The macro name may have arguments, in which case every time the macro name is encountered; the arguments associated with it are replaced by the actual arguments found in the program, as in:

#define ABS(a) (a)<0? -(a) : (a) ... printf("abs of -1 and 1: %d %d", ABS(-1), ABS(1));

Such macro substitutions in place of real functions increase the speed of the code at the price of increased program size.

  • #error

#error forces the compiler to stop compilation. It is used primarily for debugging. The general form is:

#error error_message

When the directive is encountered, the error message is displayed, possibly along with other information (depending on the compiler).

  • #include

#include instructs the compiler to read another source file, which must be included between double quotes or angle brackets. Examples are:

#include "stdio.h" #include <stdio.h>

Both of these directives instruct the compiler to read and compile the named header file. If a file name is enclosed in angle brackets, the file is searched for as specified by the creator of the compiler. If the name is enclosed in double quotes, the file is searched for

The # and ## Preprocessor Operators

The # and ## preprocessor operators are used when using a macro #define. The # operator turns the argument it precedes into a quoted string. For example, given:

#define mkstr(s) # s

the preprocessor turns the line printf(mkstr(I like C); into printf("I like C"); The ## operator concatenates two tokens. For example, given : #define concat(a, b) a ## b

int xy=10; printf("%d",concat(x, y); the preprocessor turns the last line into: printf("%d", xy);

Macros

A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.

You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords. This can be useful if you wish to hide a keyword such as const from an older compiler that does not understand it. However, the preprocessor operator defined can never be defined as a macro, and C++'s named operators cannot be macros when you are compiling C++.

To define a macro that takes arguments, you use the #define command with a list of parameters in parentheses after the name of the macro. The parameters may be any valid C identifiers separated by commas at the top level (that is, commas that aren't within parentheses) and, optionally, by white-space characters. The left parenthesis must follow the macro name immediately, with no space in between.

For example, here's a macro that computes the maximum of two numeric values: #define min(X, Y) ((X)>(Y)? (X):(Y))

Standard Predefined Macros

The standard predefined macros are specified by the C and/or C++ language standards, so they are available with all compilers that implement those standards. Older compilers may not provide all of them. Their names all start with double underscores.

FILE

This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short names specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.

  • LINE

This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro, since its "definition" changes with each new line of source code.

FILE and LINE are useful in generating an error message to report an inconsistency detected by the program; the message can state the source line at which the inconsistency was detected. For example,

fprintf (stderr, "Internal error: " "negative string length " "%d at %s, line %d.", length, FILE, LINE);

An #include directive changes the expansions of FILE and LINE to correspond to the included file. At the end of that file, when processing resumes on the input file that contained the #include directive, the expansions of FILE and LINE revert to the values they had before the # include (but LINE is then incremented by one as processing moves to the line after the #include).

DATE

This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left.

TIME

This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "23:59:01".

STDC

In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C.

  • Using the #defined, #ifndef directives helps in Prevent multiple definitions in header files.
  • Conditional compilation with the use of preprocessor directives provides a very easy way for turning the debug code on and off.
  • A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro.
  • Macros can be used for writing clear and easily comprehensible code.
  • Do remember that whenever the macro name is used, it is replaced by the contents of the macro.

Summary

The preprocessor is a program that runs prior to compilation and potentially modifies a source code file. It may add code in response to the #include directive, conditionally include code in response to #if, #ifdef, #ifndef directives or define constants using the #define directive.

A simple macro is a kind of abbreviation. It is a name which stands for a fragment of code. Some standard pre-defined Macros include FILE, LINE, DATE, TIME etc.