Preprocessors - Objective C
The objective C preprocessor is not part of the compiler, but is a separate step in the compilation process. In simplistic terms an Objective C preprocessor is just a text substitution tool and it instruct compiler to do required pre-processing before actual compilation. We'll refer to the objective C preprocessor as the OCPP.
All preprocessor commands begin with a pound symbol (#). It must be the first nonblank character, and for readability a preprocessor directive should begin in first column. Following section lists down all important preprocessor directives.
Preprocessors Examples
Analyze the following examples to understand various directives.
#define MAX_ARRAY_LENGTH 20
The directive tells the OCPP to replace instance of MAX_ARRAY_LENGTH with 20. Use #define for constants to increase readability.
These directives tell the OCPP to get Foundation Framework and add the text to the current source file. The next line tells OCPP to get myheadre.h from the local directory and add the content to the current source file.
The tell the OCPP to undefine existing FILE_SIZE and define it as 43.
This tells the OCPP to define MESSAGE only if MESSAGE isn't already defined.
The tells the OCPP to do the process the statements enclosed if DEBUG is defined. This is useful if you pass the DEBUG flag to gcc compiler at the time of compilation. This will define DEBUG, so you can turn debugging on and off on the fly during compilation.
Predefined Macros
ANSI C define a number of macros. Although each one is available for your use in programming the predefined macros should not be directly modified.
Let's try the following example.
Preprocessor Operators
The Objective C preprocessor offers following operators to help you in creating macros:
Macro Continuation(\)
A macro usually must be contained on a single line. The macro continuation operator is used to continue a macro that is too long for a single line. For example
stringize(#)
The stringize or number sign operator (#), when used withing a macro definition, converts a macro parameter into a string constant. This operator may be used only in a macro that has a specified argument or parameter list.
Token Pasting(##)
The token-pasting operator (##) within a macro definition combines two argument. It permits two separate token in the macro definition to be joined into a single token. For example
Here it happened because this example results in the following actual output from the preprocessor:
This example shows the concatenation of token##n into token34 and here we have used both stringize and token-pasting.
The defined() operator
The preprocessor defined operator is used in constant expressions to determine if an identifier is defined using #define. If the specified identifier is defined, the value is true. If the symbol is not defined, the value is false. The defined is specified as follows:
Parameterized Macros
One of the powerful function of the OCPP is the ability to simulate function using parameterized macros. For example, we might have some code to square a number as follows:
we can rewrite above code using a macros as follows:
Macros with arguments must be defined using the #define directive before they can be used. The argument list is enclosed in parentheses and must immediately follow the macro name. Spaces are not allowed between macros name and open parentheses for example:
All preprocessor commands begin with a pound symbol (#). It must be the first nonblank character, and for readability a preprocessor directive should begin in first column. Following section lists down all important preprocessor directives.
Directive | Description |
---|---|
#define | Substitutes a preprocessor macro |
#include | Insert a particular header from another file |
#undef | undefine a preprocessor macro |
#ifdef | Return true if this macro is defined |
#ifndef | Return true if this macro is not defined |
#if | Test if compile time condition is true |
#else | The alternative for #if |
#elif | #else an #if in one statement |
#error | Prints error message on stderr |
#pragma | ssues special commands to the compiler using a standardized method |
Analyze the following examples to understand various directives.
#define MAX_ARRAY_LENGTH 20
The directive tells the OCPP to replace instance of MAX_ARRAY_LENGTH with 20. Use #define for constants to increase readability.
#import <Foundation/Foundation.h>
#include "myheader.h"
#include "myheader.h"
These directives tell the OCPP to get Foundation Framework and add the text to the current source file. The next line tells OCPP to get myheadre.h from the local directory and add the content to the current source file.
#undef FILE_SIZE
#define FILE_SIZE 43
#define FILE_SIZE 43
The tell the OCPP to undefine existing FILE_SIZE and define it as 43.
#ifndef MESSAGE
#define MESSAGE " You wish"
#endif
#define MESSAGE " You wish"
#endif
This tells the OCPP to define MESSAGE only if MESSAGE isn't already defined.
#ifdef DEBUG
//STATEMENT
#endif
//STATEMENT
#endif
The tells the OCPP to do the process the statements enclosed if DEBUG is defined. This is useful if you pass the DEBUG flag to gcc compiler at the time of compilation. This will define DEBUG, so you can turn debugging on and off on the fly during compilation.
Predefined Macros
ANSI C define a number of macros. Although each one is available for your use in programming the predefined macros should not be directly modified.
Macro | Description |
---|---|
_DATE_ | The current date as a character literal in "MM:DD:YYYY" format. |
_TIME_ | The current time as a character literal in "HH:MM:SS" format. |
_FILE_ | This contains the current filename as a string literal. |
_LINE_ | This contains the current line number as a decimal constants. |
_STDC_ | Defined as 1 when the compiler compiles with the ANSI standard. |
#import <Foundation/Foundation.h>
int main()
{
NSLog(@"File :%s\n", _FILE_);
NSLog(@"Date :%s\n", _DATE_);
NSLog(@"Time :%s\n", _TIME_);
NSLog(@"Line :%s\n", _LINE_);
NSLog(@"ANSI :%s\n", _STDC_);
return 0;
}
int main()
{
NSLog(@"File :%s\n", _FILE_);
NSLog(@"Date :%s\n", _DATE_);
NSLog(@"Time :%s\n", _TIME_);
NSLog(@"Line :%s\n", _LINE_);
NSLog(@"ANSI :%s\n", _STDC_);
return 0;
}
Preprocessor Operators
The Objective C preprocessor offers following operators to help you in creating macros:
Macro Continuation(\)
A macro usually must be contained on a single line. The macro continuation operator is used to continue a macro that is too long for a single line. For example
#define message_for(a, b) \
NSLog(@#a" and " #b" :we love you\n");
NSLog(@#a" and " #b" :we love you\n");
stringize(#)
The stringize or number sign operator (#), when used withing a macro definition, converts a macro parameter into a string constant. This operator may be used only in a macro that has a specified argument or parameter list.
#import <Foundation/Foundation.h>
#define meassage_for(a, b) \
(NSLog(@#a" and " #b" :we love you\n");
int main(void)
{
message_for)Carole, Debra);
return 0;
}
#define meassage_for(a, b) \
(NSLog(@#a" and " #b" :we love you\n");
int main(void)
{
message_for)Carole, Debra);
return 0;
}
Token Pasting(##)
The token-pasting operator (##) within a macro definition combines two argument. It permits two separate token in the macro definition to be joined into a single token. For example
#import <Foundation/Foundation.h>
#define tokenpaster(n)
(NSLog(@"token" #n "= %d", token##n");
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
#define tokenpaster(n)
(NSLog(@"token" #n "= %d", token##n");
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
Here it happened because this example results in the following actual output from the preprocessor:
(NSLog(@token34 = %d", token34);
This example shows the concatenation of token##n into token34 and here we have used both stringize and token-pasting.
The defined() operator
The preprocessor defined operator is used in constant expressions to determine if an identifier is defined using #define. If the specified identifier is defined, the value is true. If the symbol is not defined, the value is false. The defined is specified as follows:
#import <Foundation/Foundation.h>
#if !defined(MESSAGE)
#define meassage "You wish" \
#endif
int main(void)
{
NSLog(@"Here is the message : %s\n", MESSAGE);
return 0;
}
#if !defined(MESSAGE)
#define meassage "You wish" \
#endif
int main(void)
{
NSLog(@"Here is the message : %s\n", MESSAGE);
return 0;
}
Parameterized Macros
One of the powerful function of the OCPP is the ability to simulate function using parameterized macros. For example, we might have some code to square a number as follows:
int square(int x){
return x *x;
}
return x *x;
}
we can rewrite above code using a macros as follows:
#define square(x) ((x)*(x))
Macros with arguments must be defined using the #define directive before they can be used. The argument list is enclosed in parentheses and must immediately follow the macro name. Spaces are not allowed between macros name and open parentheses for example:
#import <Foundation/Foundation.h>
#define MAX(x, y) ((x) > (y) ? (x) : (y)) \
int main(void)
{
NSLog(@"max between 20 and 10 is %d\n". MAX(10, 20));
return 0;
}
#define MAX(x, y) ((x) > (y) ? (x) : (y)) \
int main(void)
{
NSLog(@"max between 20 and 10 is %d\n". MAX(10, 20));
return 0;
}
No comments: