Function address in C
Program is a set of binary instruction that computer can understand execute. The executed program is called a process. Each process will be allocated for 4GB virtual memory. In general, there are 4 main parts of memory, that stores different component of a process.
- Text segment: stores binary image of the program
- Data segment: stores static and global variables
- Heap: allocates dynamic memory
- Stack: local variables
The binary image of a program is a set of instructions. The length of instruction is based on processor architecture. For example we have 4-byte instructions. A function is a subset of instructions, for example, we have a function from instruction #3 to instruction #6 (address 108 to 120). So, we have the address of this function is the smallest address of its instructions (i.e. 108).
Definition of function pointer
Function pointer is a pointer that points to the address of a function.
Define a function pointer
To define a function pointer, we use following statement
For example:
1
| typename (*function_pointer_name)(arguments) |
For example:
1
2
| Char (*getname)( int ID); Int (*calculate)( int a, int b); |
1
2
| Char (*getName)( int ID); //This is a function pointer, return a character Char *getName( int ID); //This is a function, return char* |
Assign a function address to a function pointer
We can simply assign a function address to a function pointer by its function name, which is the short way (Most of compilers support this assignment) . However, we should use the precise form with '&' operator to get the function address. Be noted that function pointer and function to be pointed should have the same prototype.
For example:
For example:
1
2
3
4
5
6
7
| void print_name( char *name){ puts (name); } void main(){ void (*p_print_name)( char *); p_print_name = print_name; //short form p_print_name = &print_name; //precise form } |
Call a function pointer
1
2
3
4
5
6
7
| int get_double( int a){ return a*2; } void main(){ int (*p_get_double)( int ); p_get_double = &get_double; int result = *p_get_double(2); //equal get_double(2); } |
Return a function pointer
We can also return a function pointer.
For example:
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| int add( int a, int b){ return a + b; } int sub( int a, int b){ return a - b; } int (*get_opcode( char opcode))( int , int ){ if (opcode == '+' ){ return &add; } else { return &subl } } void main(){ int (*p_get_opcode)( int , int ); p_get_opcode = get_op_code( '+' ); (*p_get_opcode)(1, 2); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| int add( int a, int b){ return a + b; } int sub( int a, int b){ return a - b; } typedef int (*t_opcode)( int , int ) t_opcode get_opcode( char opcode){ if (opcode == '+' ){ return &add; } else { return &sub } } void main(){ int (*p_get_opcode)( int , int ); p_get_opcode = get_opcode( '+' ); (*p_get_opcode)(1, 2); } |
Callback
Callback is to use a function pointer as a parameter to pass a function.
For example: in stdlib.h, a quicksort function is declare with the following prototype:
with
Output: 2 3 4 5 6
To understand how to implement Callback, following example illustrates a bubble sort algorithm with two selections of order (increase and decrease).
1
| void qsort ( void *base, size_t nitems, size_t size, int (*compar)( const void *, const void *); |
- base: pointer to the first element of the array to be sort
- nitems: number of item to be sort pointed by base
- size: size of each item
- compar: function that compares two elements
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| #include <stdio.h> #include <stdlib.h> #define N 5 int compare( const void *a, const void *b) { return ( *( int *)a > *( int *)b); } int main() { int i = 0; int arr[N] = {2, 6, 4, 3, 5}; qsort (arr, N, sizeof ( int ), compare); for (i = 0; i < N; i++){ printf ( "%d\t" , arr[i]); } return 0; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| #include <stdio.h> #include <stdlib.h> #include <string.h> void swap( int *a, int *b) { int c = *a; *a = *b; *b = c; } int * bubble_sort( int *number, int count, int (*sort_order)( int a, int b)) { int i = 0, j = 0; int *result = ( int *) malloc (count * sizeof ( int )); memcpy (result, number, count * sizeof ( int )); for (i = 0; i < count; i++) { for (j = i + 1; j < count; j++) { if (sort_order(result[i], result[j]) > 0) { swap(&result[i], &result[j]); } } } return result; } int increase_order( int a, int b) { return a - b; } int decrease_order( int a, int b) { return b - a; } void print_result( int *result, int count) { int i; for (i = 0; i < count; i++) { printf ( "%d\t" , result[i]); } printf ( "\n" ); } int main( int argc, char *argv[]) { int count = argc - 1; int *number = ( int *) malloc (count * sizeof ( int )); int i; for (i = 0; i < count; i++) { number[i] = atoi (argv[i + 1]); } int *result = ( int *) malloc (count * sizeof ( int )); result = bubble_sort(number, count, increase_order); print_result(result, count); result = bubble_sort(number, count, decrease_order); print_result(result, count); return 0; } |
- swap() function: swaps two elements
- bubble_sort() function: sorts an integer array, its order is controlled by a function pointer *sort_order(int a, int b). This function pointer returns true (returned value >0) or false (returned value <= 0) based on the comparison between its argument (a, b).
- increase_order() and decrease_order() functions return the comparison between their arguments.
- print_result() function: print the sorted array.
- At main function, we pass increase_order and decrease_order as arguments for the bubble_sort function.
1
2
3
| $/sort 5 1 4 6 2 $ 1 2 4 5 6 $ 6 5 4 2 1 |
Discussion:
Obviously, the selection of order in bubble sort can be implemented by the other way. We can use an integer flag to represent the order. However, the advantage of using callback is that our work can be extended and maintained more easily. The reason is we can write another function as a criterion of order, we do not have to modify inside content of bubble sort function as using a integer flag. Especially, when we work with library, we might not have permission to enter source file of a function.
Good instruction for this topic:
Function pointer
Obviously, the selection of order in bubble sort can be implemented by the other way. We can use an integer flag to represent the order. However, the advantage of using callback is that our work can be extended and maintained more easily. The reason is we can write another function as a criterion of order, we do not have to modify inside content of bubble sort function as using a integer flag. Especially, when we work with library, we might not have permission to enter source file of a function.
Good instruction for this topic:
Function pointer
Không có nhận xét nào:
Đăng nhận xét