CS计算机代考程序代写 compiler flex cache Microsoft PowerPoint – 15_C_Function_Pointers

Microsoft PowerPoint – 15_C_Function_Pointers

O
SU

C
SE

2
42

1

J.E.Jones

Required Reading: Pointers On C, Chapter 13, Sections 13.2 through 13.3

O
SU

C
SE

2
42

1

J. E. Jones

 Pretty much everything within a computer system has
an address:
◦ Every I/O device
◦ Every byte on every disk drive
◦ Every byte of memory in cache
◦ Every byte of memory in main memory
 Where OS executable code is stored
 Where OS variables are stored
 Where application program Read-Only memory is stored
 Where the stack resides
 Where the heap resides
 Where application code that is running is stored
◦ Etc.

O
SU

C
SE

2
42

1

J. E. Jones

 We’ve seen pointers to simple types before, e.g.:
int *ptr1;
float *ptr2;
char *ptr3;

 We also saw examples of pointers to pointers (these can be
used as pointers to arrays, for example):

float **sets_ptr; /* sets_ptr is a pointer to a pointer to float*/
 What about the following? What does it declare?

int *findValue(int value, int size, const int *array);

O
SU

C
SE

2
42

1

J. E. Jones

int *findValue(int value, int size, const int *array);

 This declares a function which returns a pointer
 It might do something such as the following:

/* This function is passed a value which may be an
* element of an array, and if the value is found in the
* array, it returns a pointer to it. If the element is
* not found, it returns a null pointer.
*/
int *findValue(int value, int size, const int *array);

O
SU

C
SE

2
42

1

J. E. Jones

int (*func1)();

What do you think this declares?
It’s clearly different from the declaration of a function that returns a pointer,

but what does it declare?

 Compare it to this declaration:
int *func1();

What’s the difference between the two???

O
SU

C
SE

2
42

1

J. E. Jones

int (*func1)();

 This declares a pointer to a function (or a function pointer)!
A pointer to a function makes sense, because a function consists of code and that code commences, or
begins, at some address.

 Therefore, we can declare a pointer which can be assigned an address (so we have
just declared an 8-byte variable that will contain an address). When we initialize the
variable, it will contain an address that points to the beginning of the code for some
function (the first instruction in the function).

 Notice that the function pointer is a variable; that is, it can be assigned the
addresses of different functions at different points in the program.

 The parentheses around *func1 are necessary! Otherwise, the compiler will treat
this as a declaration of a function which returns a pointer, and not a function
pointer.

O
SU

C
SE

2
42

1

J. E. Jones

 Just as a pointer to anything is not useful until it contains a
valid address, a function pointer is not useful until it actually
points to some function that we wish to call.

 Example of assignment to function pointer:
/* Prototype of function which returns the max value in an array*/

int returnMax(int size, const int *array);
/* Declare fp, and make it point to the function returnMax */

int (*fp)(int, int*);
fp = &returnMax;

or
int (*fp)(int, int*) = &returnMax;

O
SU

C
SE

2
42

1

J. E. Jones

 The type of a function pointer includes
◦ the return type, and
◦ the number and types of any parameters, in a specific order.

 For example, consider these declarations:
int returnMax(int size, const int *array);
int returnMin(int size, const int *array);
int (*fp)(int, int*) = &returnMax; OR
int (*fp)(int, int*) = &returnMin;

 This declares the variable fp to be a pointer to a function which returns an int,
and has two parameters, the first an int, and the second an int pointer.

 Because the function returnMax returns an int, and has two parameters, the
first an int, and the second an int pointer, the address of the returnMax
function can be assigned to fp.

O
SU

C
SE

2
42

1

J. E. Jones

long returnLow( int lower, int upper, char *values);
int (*fp)(int, int*);
fp= &returnLow;

 It would not be valid to assign the address of a function
which has a return type other than int to fp.

 Neither would it be valid to assign the address of a
function which has a different number of parameters, or
which has two parameters, but of different types (that is,
the first one not an int, or the second one not an int
pointer).

O
SU

C
SE

2
42

1

J. E. Jones

 NOTE: We do not have to use the address operator, &, when we assign the
address of a function to a function pointer, but we can.

 Therefore, after the declaration of returnMax, the following two
assignments to fp are equivalent:
int returnMax(int size, const int *array);
int (*fp)(int, int*) = returnMax;
int (*fp)(int, int*) = &returnMax;

 This is because the compiler always converts the function name to a
function pointer (an address) before using it (You can compare this to the
name of a variable which is an array, which the compiler also treats as a
pointer or address).

O
SU

C
SE

2
42

1

J. E. Jones

 The initialization can also be accomplished with a separate
assignment statement:
int returnMax(int size, const int *array);
int (*fp)(int, int*);
fp = returnMax; /* OR fp = &returnMax; */

 Notice that function returnMax must be declared (but not
necessarily defined) before assigning its address to the function
pointer. (i.e. at least, the prototype for returnMax must be present.)

 This is so that the compiler can do checking for type compatibility.
 The Linker/Loader will assign the final address, likely when the

final executable loads in to main memory to run.

O
SU

C
SE

2
42

1

J. E. Jones

 For the declarations on the previous slides, the call would be:
int i;
i = (*fp)(argument1, argument2);

 If the function to which fp points has no parameters, the call would be:
i = (*fp)();

 If the function to which fp points has no parameters, and no return value,
the call would be:

(*fp)();

NOTE: All these calls explicitly dereference the function pointer. Again,
the parentheses are necessary!

We can also make these calls as shown on the next slide, without
dereferencing.

O
SU

C
SE

2
42

1

J. E. Jones

 Without dereferencing fp:
int i;
i = fp(argument1, argument2);

 If the function to which fp points has no parameters, the call
without dereferencing would be:

i = fp();

 If the function to which fp points has no parameters, and no
return value, the call without dereferencing would be:

fp();

O
SU

C
SE

2
42

1

J. E. Jones

 Function pointers provide some extremely interesting, efficient
and elegant programming techniques, though they are not very
common in C programs.

 You can use them to:
– Replace switch/if statements,
– Implement callbacks*
– Realize your own run-time-binding*

 Which leads to:
Greater flexibility and better code reuse.

*beyond the scope of CSE 2421

O
SU

C
SE

2
42

1

J. E. Jones

 C treats pointers to functions just like pointers to data; so, we
can have an array of pointers to functions.

 This offers the possibility of selecting a function using an
index, and this can be used to replace an if, or a switch
statement when the functions all pass the same number and
type of parameters.

 For example:
Suppose we’re writing a program that displays a menu of
commands for the user to choose from. We can write functions
that implement these commands, and then store pointers to the
functions in an array.

O
SU

C
SE

2
42

1

J. E. Jones

 Suppose the following code:
float math_op() { /* begin function math_op */

int option;
float a, b;
printf(“Enter 1 to add, 2 to subtract, 3 to multiply, or 4 to divide:\n”);
scanf(“%d”, &option);
printf(“Enter the two operands:\n”);
scanf(“%f %f”, &a, &b);

/* code continued next slide */

O
SU

C
SE

2
42

1

J. E. Jones

switch (option) {
case 1: return (a + b);

break;
case 2: return (a – b);

break;
case 3: return (a * b);

break;
case 4: if (b!=0) return (a / b) else return(0);

break;
default: printf(“Invalid choice entered. Must be 1, 2, 3, or 4!\n”);
} /* end switch */

} /* end function math_op */

O
SU

C
SE

2
42

1

J. E. Jones

 First, define four functions to perform the four operations, add, subtract,
multiply and divide, each returning a float, and taking two float parameters;

float add(float a, float b) {return (a + b);}
float subtract(float a, float b) {return (a – b);}
float multiply(float a, float b) {return (a * b);}
float divide(float a, float b) { if (b!=0) return (a / b) else return(0);}

 Then, declare an array of four function pointers, and assign addresses of the
functions:

float (*fp_array[4])(float, float);
fp_array[0] = add; /* fp_array[0] points to add(a,b) */
fp_array[1] = subtract; /* fp_array[1] points to subtract(a,b) */
fp_array[2] = multiply; /* fp_array[2] points to multiply(a,b) */
fp_array[3] = divide; /* fp_array[3] point to divide(a,b) */

O
SU

C
SE

2
42

1

J. E. Jones

Now, rewrite function math_op as follows (Notice a pointer to the array of function
pointers is passed as a parameter to the function):

float math_op(float (**fp_array)(float, float)) {
int option;
float a, b;
printf(“Enter 1 to add, 2 to subtract, 3 to multiply, or 4 to divide:\n”);
scanf(“%d”, &option);
printf(“Enter the two operands:\n”);
scanf(“%f %f”, &a, &b);
option -=1;
if ( (option >= 0) && (option <= 3)) { return ( fp_array[option](a, b)); } else printf(“Invalid choice entered. Must be 1, 2, 3, or 4!\n”); } Note: if ( (option >= 0) && (option <= 3)) could have been written as if((unsigned)option <= 3) why?? Is that a better option?? O SU C SE 2 42 1 J. E. Jones Notice how the pointer to the array of function pointers is passed as a parameter to math_op() #include
float add(float a, float b) {return (a + b);}
float subtract(float a, float b) {return (a – b);}
float multiply(float a, float b) {return (a * b);}
float divide(float a, float b) {if (b!=0)return (a/b) else return(0);}

int main () {
float result;
float (*fp_array[4]) (float, float) = {add, subtract, multiply, divide};
result = math_op(fp_array);
printf(“The result is: %f\n”, result);
return 0;

}