The document discusses various C preprocessor directives including #include, #define, #ifdef, #ifndef, #if, #else, #endif, #error, #line, #pragma, and assert. It explains what each directive does, provides examples of their usage, and describes properties of macros and how they differ from functions. Some key points covered include how #include is used to include header files, how #define defines macros, how conditional compilation directives like #if/#else/#endif work, and how assert can be used to check for illegal values.
2. Introduction
Program that Processes or Analyzes the source code
file before given to the Compiler is called as Pre-
Processor.
Preprocessing Occurs before program compiled due
to
Inclusion of external files.
Definition of symbolic constants.
Macros.
Conditional compilation.
Conditional execution.
3.
4.
5. #include
Specifies that the preprocessor should read in the contents of the
specified file.
usually used to read in type definitions, prototypes, etc.
Two forms
#include <filename>
For standard library header files.
Searches pre designated directories.
#include "filename"
Searches in current directory.
Normally used for programmer-defined files.
6. User defined header files:
A header file has file-extension ‘.h’
These header files typically contain “public”
information like
type declarations
macros and other definitions
function prototypes
These header files are included by files that need
that public information
#include “myheaderfile.h”
7. #define
#define is the preprocessor directive for the macro.
Macros are generally used to define constant values
that are being used repeatedly in program.
Structure of simple macros:
#define identifier replacement_list
Examples:
#define BUFFERSZ 1024
#define WORDLEN 64
8. Using simple macros
We just use the macro name in place of the value, e.g.:
#define BUFLEN 1024
#define Pi 3.1416
…
char buffer[BUFLEN];
…
area = Pi * r * r;
9. Properties of macros
Takes no memory.
Name not be seen by debugger (only for
replacement of text).
Do not have specific data type.
Macro without arguments Treated like a symbolic
constant.
Macro with arguments Performs a text substitution.
No data type checking.
Macros may be nested.
10. Macro Vs. Function
Macro Function
Macro is Preprocessed. Function is Compiled.
No Type Checking . Type Checking is Done.
Speed of Execution is Faster. Speed of Execution is Slower.
Before Compilation macro name is
replaced by macro value.
During function call , Transfer of Control
takes place.
Useful where small code appears many
times.
Useful where large code appears many
times.
Generally Macros do not extend beyond
one line.
Function can be of any number of lines.
Macro does not Check Compile Errors. Function Checks Compile Errors.
11. Advanced Macro Tricks
The C pre processor offers following operators to help
you in creating macros:
Macro Continuation ()
Stringize (#)
Token Pasting (##)
12. Macro Continuation
The macro continuation operator is used to continue a
macro that is too long for a single line.' ' indicate line
contuation.
The slash tells the preprocessor that the macro continuous
to the next line.
Ex:
#define SWAP(a, b) {
a ^= b;
b ^= a;
a
^= b; }
13. Stringize
The stringize or number-sign operator ('#'), when
used within 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.
14. Example
#define STR(x) #x
#define XSTR(x) STR(x)
#define ONE 1
Macro call Result of Macro Expansion
STR(n "n" 'n') "n "n" 'n'“
STR(ONE) "ONE“
XSTR(ONE) "1“
XSTR("hello") ""hello""
15. Token Pasting
Token Pasting(##) permits separate tokens to be
joined into a single token. sometimes its called as
“Merging” operator.
#define ArgArg(x, y) x##y
#define Jitterbug 3
Macro call Result of Macro Expansion
ArgArg(lady, bug) ladybug
ArgArg(Jitter, bug) 3
16. Predefined Macros
The standard predefined macros are specified by the
relevant language standards, so they are available
with all compilers that implement those standards.
We cannot use these predefined macros in #define
and #undef.
__FILE__: This macro expands to the name of the
current input file, in the form of a C string constant.
__LINE__: This macro expands to the current input
line number, in the form of a decimal integer constant.
17. __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.
__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.
__STDC__: This macro expands to the constant 1, to
signify that this compiler conforms to ISO Standard
C.
__ASSEMBLER__: This macro is defined with value
1 when preprocessing assembly language.
18. #undef
Un defines symbolic constant or macro.
Can later be redefined.
#include <stdio.h>
#define value 100
void main()
{
printf("First defined value : %dn",value);
#undef value // undefining variable
#define value 600 // redefining the same for new value
printf("value after undef & redefine:%d",value);
}
19. Conditional Compilation
Conditional Compilation Directives allow us to
include certain portion of the code depending upon
the output of constant expression.
Conditional Compilation Directives are #if, #else,
#endif, #ifdef, #ifndef,#pragma,#undef.
Every #if ends with #endif.
#elif is "else if”.
#ifdef short for #if defined(name).
#ifndef short for #if !defined(name).
20. #if
#include <stdio.h>
#define a 100
int main()
{
#if (a==100)
printf("This line will be added in this C file);
#else
printf("This line will not be added in this c file");
#endif
return 0;
}
21. Commenting the code
#if 0
code commented out
#endif
To enable code, change the value from 0
to 1
22. #ifdef
#include <stdio.h>
#define VALUE 100
int main()
{
#ifdef VALUE
printf("VALUE is definedn");
#else
printf("VALUE is not definedn");
#endif
return 0;
}
23. #ifndef
#include <stdio.h>
#define A 100
int main()
{
#ifndef B{
printf("B is not defined");
#define B 300
}
#else
printf("B is already defined”);
#endif
return 0;
}
24. Line numbers
#line is used to renumbers subsequent code
lines, starting with integer.
#line 100 means next source code line is
numbered as 100.
For error purposes we will use this line
numbers.
Can make syntax errors more meaningful.
Line numbers do not appear in source file.
25. Example
#include <stdio.h>
#define LINE200 200
int main(void){
func_1();
func_2();
}
#line 100
func_1(){
printf("Func_1 - the current line number is %dn",_ _LINE_ _);
}
#line LINE200
func_2(){
printf("Func_2 - the current line number is %dn",_ _LINE_ _);
}
26. #error
The #error directive causes the preprocess to print a
diagnostic error message, using the argument as a part
of the message.
Useful to trap incorrect conditions in conditional
compilation.
Compilation is aborted when this directive is
invoked.
27. Example
#ifndef __MATH_H
#error First include then compile
#else
void main()
{
float a,b=25;
a=sqrt(b);
printf(“%f”,a);
}
#endif
Result: First include then compile
28. #pragma
#pragma directive is used to control the actions of
the compiler in a particular portion of a program
without affecting the program.
pragma directive varies from one compiler to
another compiler .
If compiler does not recognize particular pragma
then it ignore the pragma statement without showing
any error or warning message.
29. We can aviod the structure padding using #pragma.
The default compiler alignment is of 4 bytes. we
can use #pragma to change the byte alignment to 1
byte.
For that, do the following steps:
1.Push the current compiler alignment into the stack.
2.Set the alignment into 1 byte.
3.Declare the structure.
4.Restore the default compiler alignment from the
stack.
30. Example
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
struct EX
{
char a;
short int b;
char c;
int d;
};
#pragma pack(pop) /* restore original alignment from stack */.
Without #pragma,the size of the structure is 12 bytes.
With #pragma,the size of the structure is 8 byets.
gcc -fpack-struct filename.c :
This is command for remove the struct padding at compilation time .
31. #pragma startup & exit
pragma startup always execute the function before the main
function.
pragma exit always execute the function after the main
function.
If more than one startup directive then priority decides
which will execute first.
For startup, Lower value will have higher priority i.e
function will execute first.
If more than one exit directive then priority decides which
will execute first.
For exit, Higher value will have higher priority i.e function
will execute first.
32. Example
void fun1();
void fun2() ;
#pragma startup fun1 105
#pragma startup fun2
#pragma exit fun2
#pragma exit fun1 105
void main(){
printf("nI am in main");
}
void fun1(){
printf("nI am in fun1");
}
void fun2(){
printf("nI am in fun2");
}
33. #pragma warn
In c there are many warning messages which can be on or
off with help of #pragma warn.
#pragma warn +xxx
#pragma warn –xxx
#pragma warn .xxx
Where + means on
-means off
. means on/off (toggle)
xxx will indicate particular warning code in thee alphabet.
34. Example
#pragma warn –rvl
int main()
{
Printf(“It will not show any warning message”);
}
Output: It will not show any warning message.
When you will execute the above program then
compiler will not show the warning message like
function should return a value.
35. Assertions
assert is a macro, Header is <cassert> .
Tests value of an expression.
If 0 (false) prints error message, calls abort terminates
program, prints line number and file.
Good for checking for illegal values.
If 1 (true), program continues as normal
assert( x <= 10 );
To remove assert statements No need to delete them
manually
#define NDEBUG
All subsequent assert statements ignored.