3.6 - Preprocessors
- One of the step performed before compilation
- Is a text substitution tool and it instructs the compiler to do required pre-processing before the actual compilation
- Instructions given to preprocessor are called preprocessor directives and they begin with “#” symbol
- Few advantages of using preprocessor directives would be,
- Easy Development
- Readability
- Portability
Preprocessor – Compilation Stages
- Before we proceed with preprocessor directive let's try to understand the stages involved in compilation.
- Some major steps involved in compilation are
- Preprocessing (Textual replacement)
- Compilation (Syntax and Semantic rules checking)
- Assembly (Generate object file(s)).
- Linking (Resolve linkages)
Preprocessor – Directives
#include #elif #define #error #undef #warning #ifdef #line #ifndef #pragma #else # #endif ## #if #else
Preprocessor – Header Files
- A header file is a file containing C declarations and macro definitions to be shared between several source files.
- Has to be included using C preprocessing directive ‘#include'
- Header files serve two purposes:
- Declare the interfaces to parts of the operating system by supplying the definitions and declarations you need to invoke system calls and libraries.
- Your own header files contain declarations for interfaces between the source files of your program.
Preprocessor – Header Files vs Source Files
● Declarations ● Function and variable definitions
● Sharable/reusable ● Non sharable/reusable
● #defines ● #defines
● Datatypes ● Datatypes
● Used by more than 1 file
Preprocessor – Header Files - Syntax
Syntax
#include <file.h>
System header files
It searches for a file named file in a standard list of system directories
#include “file.h”
- Local (your) header files
Header Files – Search Path
- On a normal Unix system GCC by default will look for headers requested with #include <file> in:
/usr/local/include libdir/gcc/target/version/include /usr/target/include /usr/include
You can add to this list with the -I command-line option
“gcc -print-prog-name=cc1 -v” would search the path info
Header Files – Once-Only
- If a header file happens to be included twice, the compiler will process its contents twice causing an error
- E.g. when the compiler sees the same structure definition twice, This can be avoided like:
#ifndef NAME #define NAME /* The entire file is protected */ #endif
Macro – Object-Like
- An object-like macro is a simple identifier which will be replaced by a code fragment
- It is called object-like because it looks like a data object in code that uses it.
- They are most commonly used to give symbolic names to numeric constants
#define SYMBOLIC_NAME CONSTANTS Example ------- #define BUFFER_SIZE 1024
Macro – Arguments
- Function-like macros can take arguments, just like true functions
- To
define a macro that uses arguments, you insert parameters between the
pair of parentheses in the macro definition that make the macro function
like
Example
#include#define SET_BIT(num, pos) (num | (1 << pos)) int main() { SET_BIT(0, 2); return 0; }
Macro – Multiple Lines
- You may continue the definition onto multiple lines, if necessary, using backslash-newline.
- When the macro is expanded, however, it will all come out on one line
Example
#include#define SWAP(a, b) \ { \ int temp = a; \ a = b; \ b = temp; \ } int main() { int num1 = 10, num1= 20; SWAP(num1, num2); printf(“%d %d\n”, num1, num2); }
Macro – Standard Predefined
- Several object-like macros are predefined; you use them without supplying their definitions.
- Standard
are specified by the relevant language standards, so they are available
with all compilers that implement those standards
Example
#includeint main() { printf(“Program: \“%s\” ”, __FILE__); printf(“was compiled on %s at %s. ”, __DATE__, __TIME__); printf(“This print is from Function: \”%s\” at line %d\n”, __func__, __LINE__); return 0; }
Preprocessor – Conditional Compilation
- A conditional is a directive that instructs the preprocessor to select whether or not to include a chunk of code in the final token stream passed to the compiler
- Preprocessor conditionals can test arithmetic expressions, or whether a name is defined as a macro, or both simultaneously using the special defined operator
- A conditional in the C preprocessor resembles in some ways an if statement in C with the only difference being it happens in compile time
- Its purpose is to allow different code to be included in the program depending on the situation at the time of compilation.
- There are three general reasons to use a conditional.
- A program may need to use different code depending on the machine or operating system it is to run on
- You may want to be able to compile the same source file into two different programs, like one for debug and other as final
- A conditional whose condition is always false is one way to exclude code from the program but keep it as a sort of comment for future reference
Conditional Compilation - ifdef
Syntax
Syntax
#ifdef MACRO /* Controlled Text */ #endif
Conditional Compilation - defined
Syntax
Syntax
#if defined (ERROR) && (WARNING) /* Controlled Text */ #endif
Conditional Compilation - if
Syntax
Syntax
#if expression /* Controlled Text */ #endif
Conditional Compilation - else
Syntax
#if expression /* Controlled Text if true */ #else /* Controlled Text if false */ #endif
Conditional Compilation - elif
Syntax
#if DEBUG_LEVEL == 1 /* Controlled Text*/ #elif DEBUG_LEVEL == 2 /* Controlled Text */ #else /* Controlled Text */ #endif
Preprocessor – Diagnostic
- The directive ‘#error’ causes the preprocessor to report a fatal error. The tokens forming the rest of the line following ‘#error’ are used as the error message
- The directive ‘#warning’ is like ‘#error’, but causes the preprocessor to issue a warning and continue preprocessing. The tokens following ‘#warning’ are used as the warning message
...
Post a Comment