|
@ -0,0 +1,181 @@ |
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// macro for easier using of saferfree function |
|
|
|
|
|
#define safeFree(p) saferFree((void**) &(p)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// typedefs |
|
|
|
|
|
typedef int (*t_fptr)(int); |
|
|
|
|
|
typedef int (*t_fptr_op)(int, int); |
|
|
|
|
|
typedef void (*t_fptr_base)(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function declarations |
|
|
|
|
|
void allocateArray(int **arr, size_t size, int value); |
|
|
|
|
|
void allocateArrayWrong(int *arr, int size, int value); |
|
|
|
|
|
void saferFree(void **pointer); |
|
|
|
|
|
int square(int num); |
|
|
|
|
|
int add(int a, int b); |
|
|
|
|
|
int sub(int a, int b); |
|
|
|
|
|
//int err(int a, int b); |
|
|
|
|
|
void err(void); |
|
|
|
|
|
int operation(t_fptr_op op, int a, int b); |
|
|
|
|
|
t_fptr_op select(char opc); |
|
|
|
|
|
void initialiseOperationsArray(void); |
|
|
|
|
|
int evalArray(char opc, int a, int b); |
|
|
|
|
|
t_fptr_op operations[128] = {NULL}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// pointer by reference |
|
|
|
|
|
void allocateArray(int **arr, size_t size, int value) { |
|
|
|
|
|
int *array = (int*) malloc(size * sizeof(int)); |
|
|
|
|
|
if (array != NULL) { |
|
|
|
|
|
for (size_t index = 0; index < size; index++) { |
|
|
|
|
|
array[index] = value; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
*arr = array; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// pointer by value -> this will not work |
|
|
|
|
|
void allocateArrayWrong(int *arr, int size, int value) { |
|
|
|
|
|
arr = (int*) malloc(size * sizeof(int)); |
|
|
|
|
|
if(arr != NULL) { |
|
|
|
|
|
for(int i = 0; i < size; i++) { |
|
|
|
|
|
arr[i] = value; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// safer free version which checks for NULL pointer |
|
|
|
|
|
// assigns NULL after freeing the pointer |
|
|
|
|
|
void saferFree(void **pointer) { |
|
|
|
|
|
if (pointer != NULL && *pointer != NULL) { |
|
|
|
|
|
free(*pointer); |
|
|
|
|
|
*pointer = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// simple (unsafe) addition function |
|
|
|
|
|
int add(int a, int b) { |
|
|
|
|
|
return a + b; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// simple (unsafe) subtract function |
|
|
|
|
|
int sub(int a, int b) { |
|
|
|
|
|
return a - b; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int operation(t_fptr_op op, int a, int b) { |
|
|
|
|
|
return op(a, b); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// simple (unsafe) square function |
|
|
|
|
|
int square(int num) { |
|
|
|
|
|
return num * num; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function selector |
|
|
|
|
|
// returns pointer to selected function |
|
|
|
|
|
t_fptr_op select(char opc) { |
|
|
|
|
|
switch (opc) { |
|
|
|
|
|
case '+': return add; |
|
|
|
|
|
case '-': return sub; |
|
|
|
|
|
default : return (t_fptr_op) err; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// error function |
|
|
|
|
|
void err(void) { //int a, int b) { |
|
|
|
|
|
fprintf(stderr, "invalid operation!\n"); |
|
|
|
|
|
//return 42; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// evaluate given operation on a & b |
|
|
|
|
|
// operation is given by function pointer |
|
|
|
|
|
int eval(char opc, int a, int b) { |
|
|
|
|
|
t_fptr_op operation = select(opc); |
|
|
|
|
|
return operation(a, b); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// initialise operations array |
|
|
|
|
|
// with pointers to add & sub functions |
|
|
|
|
|
void initialiseOperationsArray(void) { |
|
|
|
|
|
operations['+'] = add; |
|
|
|
|
|
operations['-'] = sub; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// eval function which works with |
|
|
|
|
|
// the array of function pointers |
|
|
|
|
|
int evalArray(char opc, int a, int b) { |
|
|
|
|
|
t_fptr_op operation; |
|
|
|
|
|
operation = operations[opc]; |
|
|
|
|
|
return operation(a, b); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main (void) { |
|
|
|
|
|
|
|
|
|
|
|
// variable definitions |
|
|
|
|
|
size_t size = 8; |
|
|
|
|
|
int value = 5; |
|
|
|
|
|
int *vector = NULL; |
|
|
|
|
|
//int (*fptr0) (int); |
|
|
|
|
|
t_fptr fptr0; |
|
|
|
|
|
|
|
|
|
|
|
// print vector address |
|
|
|
|
|
printf("before malloc: %p\n", vector); |
|
|
|
|
|
|
|
|
|
|
|
// function calls |
|
|
|
|
|
allocateArray(&vector, size, value); |
|
|
|
|
|
//allocateArrayWrong(vector_wrong, size, value); |
|
|
|
|
|
|
|
|
|
|
|
for (size_t index = 0; index < size; index++) { |
|
|
|
|
|
printf("%u : %d\n", (unsigned int) index, vector[index]); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// print vector address |
|
|
|
|
|
printf("before safeFree: %p\n", vector); |
|
|
|
|
|
|
|
|
|
|
|
//saferFree((void**)&(vector)); |
|
|
|
|
|
safeFree(vector); |
|
|
|
|
|
|
|
|
|
|
|
// print vector address after free |
|
|
|
|
|
printf("after safeFree: %p\n", vector); |
|
|
|
|
|
|
|
|
|
|
|
// function pointer fptr0 now points to square() |
|
|
|
|
|
fptr0 = square; |
|
|
|
|
|
|
|
|
|
|
|
// call function which fptr0 points to |
|
|
|
|
|
printf("%d squared is %d\n", value, fptr0(value)); |
|
|
|
|
|
|
|
|
|
|
|
// test of function pointers as function parameters |
|
|
|
|
|
printf("%u + %d = %d\n", (unsigned int) size, value, operation(add, size, value)); |
|
|
|
|
|
printf("%u - %d = %d\n", (unsigned int) size, value, operation(sub, size, value)); |
|
|
|
|
|
|
|
|
|
|
|
// test of fucntion pointer returning |
|
|
|
|
|
printf("%d\n", eval('t', size, value)); |
|
|
|
|
|
|
|
|
|
|
|
// function pointer casting |
|
|
|
|
|
t_fptr_base basePointer; |
|
|
|
|
|
t_fptr_op fptrFirst = add; |
|
|
|
|
|
basePointer = (t_fptr_base) fptrFirst; |
|
|
|
|
|
fptrFirst = (t_fptr_op) basePointer; |
|
|
|
|
|
printf("%d\n", fptrFirst(5,6)); |
|
|
|
|
|
|
|
|
|
|
|
// return value |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |