0% found this document useful (0 votes)
1K views

C - Session 14

The document discusses C language function pointers and preprocessor directives. Function pointers allow a function to be invoked indirectly through a pointer variable that stores the function's address. Preprocessor directives are instructions to the preprocessor that modify how the source code is compiled. Key directives include #define for macros, #include for files, and #if/#else for conditional compilation.

Uploaded by

r am
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

C - Session 14

The document discusses C language function pointers and preprocessor directives. Function pointers allow a function to be invoked indirectly through a pointer variable that stores the function's address. Preprocessor directives are instructions to the preprocessor that modify how the source code is compiled. Key directives include #define for macros, #include for files, and #if/#else for conditional compilation.

Uploaded by

r am
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

C Language

Created By
SATISH KHANNA

VEDAIIT
HYDERABAD
C Language
Session 14

• Function Pointers
• Pre-processor Directives
• Define Directives (Macros)
• Conditional Compilation Directives
• Include Directives
Function Pointers
• A function pointer can point to the starting address of the function
segment (A set of statements that define a function).
• It can then be used to invoke the referent function to which it is
currently pointing.
• As with any other pointer, the declaration of a function pointer is
dependent on the referent function’s prototype. A declaration of
function pointer, more specifically, depends on the signature of the
function and return type of the function.
• Declaration of a function pointer
Syntax: return-type (*pointer-name)(param-type-list);

Example:
int (*fptr1)(int, int);

The statement declares a function pointer fptr1 that can point to any
function that has two int parameters and also has an int return type.
Function Pointers
• Define two functions that have two int parameters & return an int
int findSum (int a, int b) {
return (a + b);
}

int findDiff (int a, int b) {


return (a – b);
}

• Set pointer to point to findSum() function


fptr1 = findSum;

• Invoking function through function pointer


int res1 = fptr1(10, 20); //OR
int res1 = (*fptr)(10, 20);
printf("%d\n", res); // OUTPUT: 30

• NOTE: The name of a function is a constant function pointer to the


starting address of that function's segment.
Function Pointers
• #include<stdio.h>

int findSum(int a, int b) {


return a+b;
}
int findDiff(int a, int b) {
return a-b;
}
int main() {
int (*fptr)(int, int);

fptr = findSum;
int res = fptr(10, 20); // invokes findSum()
printf("%d\n", res); // OUTPUT: 30

fptr = findDiff;
res = (*fptr)(25, 15); // invokes findDiff()
printf("%d\n", res); // OUTPUT: 10

return 0;
}
Function Pointers
• Passing function pointer as an argument to another function

int compute(int (*fp1)(int,int),int a, int b) {


int result;
result = fp1(a, b);
return result;
}

Call the compute function when fptr1 points to findSum()

fptr1 = findSum;
res1 = compute(fptr1, 10, 20);
printf(“%d\n”, res1); // 30

Call the compute function when fptr1 points to findDiff()

fptr1 = findDiff;
res1 = compute(fptr1, 100, 40);
printf(“%d\n”, res1); // 60
Pre-processor Directives
• A pre-processor directive is an instruction to the pre-processor
program that is run as the first stage of compiling a C program.
• It can be given in a source code file or at command line during
compiling using options of gcc compiler.
• In the source code file a directive begins with a # symbol followed by
predefined directive. The directive is terminated using a newline.
This means, each directive should be on an independent line.
However, if a directive has to span to next line the newline should
be escaped using backslash \ character.
• In general the directives are of 4 types:
Define Directive
Conditional Compilation Directive
Include Directive
Other Directives
• Define Directive
This directive is used to associate a macro name with a string. The
macro name can then be used anywhere in the program where
associated string is required.
Pre-processor Directives
• At pre-processing stage the macro is blindly substituted with
associated string. The macro name can also have parameters.
• #define NAME[ (parameter name list) ] stringVal
• The directive defines a new macro named NAME and associates it
with the following string stringVal. The macro can optionally have
in parentheses one or more parameter names separated with
comma.
• Once defined, the macro NAME can be used anywhere in the
program where stringVal is required.
Macro name is in UPPERCASE, by convention.
• Macros are of 4 types:
Simple Macro
Macro with parameters
Nested Macro
Pre-defined Macros
Pre-processor Directives
• Simple Macro
#define SIZE 10
The directive defines a macro named SIZE with associated string 10.
Once SIZE is defined as a macro, it can be used anywhere in the
program where the value 10 is required.
For example, SIZE can be used in a declaration of an array and in a
loop for iterating through the array, as under:
int arr[SIZE], i;
for(i=0; i<SIZE; i++)
scanf("%d", &arr[i]);
At pre-processing stage wherever the macro SIZE is found it is
replaced with 10. However, the replacement does not occur if the
macro is in double quoted string.
Printf("SIZE=%d", SIZE); //Output: SIZE=10
• The value associated with the macro can be an expression. However,
the expression is not evaluated at the time of macro substitution.
#define M 7 + 20
#define N 5 + 4

int res = M/N;


Pre-processor Directives
• On substitution the macros M and N are replaced with associated
strings 7+20 and 5+4 respectively.
int res = 7+20/5+4;

At run-time the expression is evaluated to 15 since division operator


has higher precedence than addition operator.
However, if the intention is to perform additions before division
then while defining macro extra parentheses should be placed
around the associated expressions and to avoid any side effects after
substitution, as under:
#define M (7+20)
#define N (5+4)

In this case, the expression M/N is substituted as under


int res = (7+20)/(5+4);
and evaluated to 3.
Pre-processor Directives
• Macro with parameters
#define MAX(a, b) (((a)>(b))?(a):(b))
The directive defines a parameterized macro named MAX with two
parameters a and b.
Two arguments must be passed to this macro when it is used in
program code, as under:
int x = 10, y = 20, res;
res = MAX(x, y);
During pre-processing stage the arguments x and y are copied to
parameters a and b respectively and then macro substitution takes
place and res stores 20.
• Use of macro MAX is similar to a function call but without the
overheads of calling a function.
However, care should be taken while using a macro like a function
since it can have some unwanted side effects that a function call does
not have.
If findMax( ) is defined as a function and called as under, it returns 21
int x=10, y=20, res1;
res1 = findMax(x,++y); // res1 is 21
If used as a macro defined above, in a similar manner, it returns 22
res1 = Max(x, ++y); // res1 is 22
Pre-processor Directives
• Nested Macros
A macro, once defined, can be used in an expression associated with
another macro.
#define SQUARE(a) ((a)*(a))
#define CUBE(a) (SQUARE(a)*(a))
Macro CUBE uses another Macro SQUARE that should be defined
earlier. When CUBE is used in program code, it will be first substituted
with SQUARE and then SQUARE is further substituted with a*a.
res = CUBE(5); // 125
• A Macro can be undefined in source file using #undef directive.
#undef macro-name
#undef size
• A Macro can also be defined at compile time using -D option of gcc
% gcc -DMacroName[=value] sourcefile.c
value is optional, default being 1
% gcc -Dsize=10 test01.c
• A Macro can also be undefined at compile time using -U option of gcc
% gcc -USIZE test.c
Pre-processor Directives
• NOTE:
Macros defined in file using #define directive override macros defined
with the same name at compile time. C does not allow
same macro to be defined more than once, or to undefine a macro that has
not been defined and generates error.

• Pre-defined Macros
__LINE__ stores current line number of source code file
__DATE__ stores most recent date of compilation of program
__TIME__ stores most recent time of compilation of program
__func__ stores name of current function
__FILE__ stores name of program file
__STDC__ stores 1 if compiler complies with ANSI C standard

• win32 stores 1 if O.S. is 32-bit windows


__linux__ stores 1 if O.S. is Linux
__unix__ stores 1 if O.S. is Unix
windows stores 1 if O.S. is windows

• CAUTION:
Be alert to the side effects of macros, before using a particular macro.
Pre-processor Directives
• Conditional Compilation Directives
The conditional compilation directives are used to include or exclude a
piece of code from compilation.
• Based on these directives the pre-processor selects which code from
the source code file should be passed to the compiler.
• The directives are:
#if #elif #else #endif
#ifdef #ifndef #undef defined
• For example, a macro with the same name cannot be defined again if
it is already defined earlier. So, the macro should be defined or even
undefined conditionally as under:
• #ifndef SIZE
#define SIZE
#endif
• #ifdef SIZE //OR #if defined SIZE
#undef SIZE
#endif
Pre-processor Directives
• When developing a C program for a given application it is known that
there are slight differences in the code being developed for different
O.S. or platforms.
Now, instead of developing separate programs, one for each platform,
it is better to develop a single program that works for all platforms by
including code using conditional compilation directives.
The pre-processor program identifies the platform based on
predefined macros for different platforms and includes code meant for
the specific platform being currently used.
• Example 1
#include<stdio.h>
int main() {
#ifdef _WIN32
printf("Windows 32-bit & 64-bit\n");
#elif defined _WIN64
printf("Windows 64-bit\n");
#elif defined __linux__
printf("Linux\n");
#elif defined __unix__
printf("Unix\n");
#else
printf("Some Other\n");
#endif
}OUTPUT: Linux
Pre-processor Directives
• Include Directive
#include<[path/]filename.h>
#include<stdio.h>
The directive includes the named header file (.h extension) into the
source code file at the place where this directive is placed.
The file to be included is searched at the standard installation
location (/usr/include).
It is also possible to provide path with file name or use command
line option -I<path> at compile time.

#include" [path/]filename.h"
#include "myfun.h"
Double quotes may be used around filename for user defined
header files.
• NOTE:
C does not allow same header file to be included more than once,
directly or indirectly.
Pre-processor Directives
• Providing Include Guards
Preventing double inclusion of header file file3.h
• File: file1.c
#include<file2.h>
#include<file3.h>
//code
• File: file2.h
#include<file3.h>
//code
• File: file3.h
#ifndef FILE3_H
#define FILE3_H
//code
#endif
• In file1.c the file file3.h is included twice; once directly and again
indirectly through file2.h
• To avoid double inclusion of file3.h the entire code of file3.h is placed
under conditional compilation. When file3.h is included for the first
time a new macro FILE3_H is defined and the code of file is actually
included.
However, when an attempt is made to include this file for the second
and subsequent time, the macro is already defined and prevents
inclusion of same code again.
Pre-processor Directives
• Other Directives
#line num [filename]
#error message
#warning message
# stringization operator
## concatenation operator
• Example 1
#include<stdio.h>
#define X 20
int main()
{
printf("%d\n", X);
#if X>10
#error X cannot be greater than 10
#endif
return 0;
}
OUTPUT: test.c:6:10: #error X cannot be greater than 10
Pre-processor Directives
• Example 2
#include<stdio.h>
#define paster(n) printf("token"#n"=%d", token##n);

int main() {
int token1 = 10, token2 = 20, token3 = 30;

paster(1);
paster(2);
paster(3);

return 0;
}
OUTPUT:
token1=10
token2=20
token3=30

You might also like