Usage of function pointers and state machines

Original link: https://blog.csdn.net/liebecl/article/details/76718767 1 function pointer and state machine In many large...
2.1 a simple switch scenario
2.2 replace switch with function pointer

Original link: https://blog.csdn.net/liebecl/article/details/76718767

1 function pointer and state machine

In many large integrated systems, the state machine will be used to jump to the specified function, and the use of the state machine is inseparable from the function pointer, structure array, etc. the following describes the usage of the function pointer and the state machine.

Structure array
Usually, the elements of the array we contact are numbers or characters, which are generally called integer array or character array, and the structure array is the element of the array. It is a structure, which is still an array in essence.

Function pointer
Function pointer, as the name suggests, is a pointer, a pointer to a function. Just as a pointer can point to integer variables, character variables, and arrays, it can point to a function.

//A function pointer is defined, the input parameters of the function are a and b, the return value is integer, and a func is defined_ Pointer type pointer typedef int (*func_pointer)(int a,int b); //Define a CTL whose member is a pointer_ Info type structure typedef struct { func_pointer func; }ctl_info; //Define the element as a two-dimensional array of the structure. The assignment of the array should be a member of the structure, that is, a function pointer static const ctl_info ctl_matrixTable[2][2]= { {{&func00},{&func01}}, {{&func10},{&func11}}, } //Definition of function int func00(int a,int b) { return 0; } /*Real use*/ //Also define a function pointer func_pointer pointer; //Acquisition of function pointer pointer = ctl_matrixTable[0][1].func; //Function call result = (pointer)(a,b);
2 use function pointer instead of switch case

Original link: https://blog.csdn.net/weixin_45252450/article/details/109431954

2.1 a simple switch scenario

#include <stdio.h> int main(){ int number; printf("please enter the number:\n"); scanf("%d",&number); switch (number) { case 0: printf("case 0\n"); break; case 1: printf("case 1\n"); break; case 2: printf("case 2\n"); break; case 3: printf("case 3\n"); break; case 4: printf("case 4\n"); break; case 5: printf("case 5\n"); break; default: printf("case don't exist\n"); break; } return 1; }

2.2 replace switch with function pointer

#include <stdio.h> void PrintfFunc0(){ printf("case 0\n"); } void PrintfFunc1(){ printf("case 1\n"); } void PrintfFunc2(){ printf("case 2\n"); } void PrintfFunc3(){ printf("case 3\n"); } void PrintfFunc4(){ printf("case 4\n"); } void PrintfFunc5(){ printf("case 5\n"); } void (*pfunc[6])(); //Define an empty array of function pointers void MyFunction(int number){ (*pfunc[number])(); } void Register(){ pfunc[0]=PrintfFunc0; pfunc[1]=PrintfFunc1; pfunc[2]=PrintfFunc2; pfunc[3]=PrintfFunc3; pfunc[4]=PrintfFunc4; pfunc[5]=PrintfFunc5; } int main(){ int number; Register(); printf("please enter the number:\n"); scanf("%d",&number); MyFunction(number); return 1; }

The advantage of this is that there are not a large number of switch case branches in the main function. Separate the logic of each branch as a function, put these function pointers into an array, and then find the corresponding function pointers according to number.
Due to the limitation of function pointer array, these functions must have the same function prototype.
The above change is unsafe because when number is 6 or greater, the corresponding function pointer cannot be found, and the program will have a segment error. The traditional switch case will execute the code at defalut.

Safer use
Make some modifications to make full use of stl library.

#include <stdio.h> #include <map> using namespace std; void PrintfFunc0(){ printf("case 0\n"); } void PrintfFunc1(){ printf("case 1\n"); } void PrintfFunc2(){ printf("case 2\n"); } void PrintfFunc3(){ printf("case 3\n"); } void PrintfFunc4(){ printf("case 4\n"); } void PrintfFunc5(){ printf("case 5\n"); } map<int,void (*)()>MapIntToFunc; void MyFunction(int number){ if(MapIntToFunc.find(number)!=MapIntToFunc.end())//First find out whether there is a corresponding function pointer (*MapIntToFunc[number])(); else printf("case don't exist\n"); } void Register(){ MapIntToFunc[0]=PrintfFunc0; MapIntToFunc[1]=PrintfFunc1; MapIntToFunc[2]=PrintfFunc2; MapIntToFunc[3]=PrintfFunc3; MapIntToFunc[4]=PrintfFunc4; MapIntToFunc[5]=PrintfFunc5; } int main(){ int number; Register(); printf("please enter the number:\n"); scanf("%d",&number); MyFunction(number); return 1; }

Switch case will generate a skip table with the number of table items of case quantity + 1. The program first determines whether the switch variable is greater than (less than) the maximum (minimum) case constant. If it is greater than (less than), it will skip to the default branch for processing; Otherwise, obtain the address of the jump table item whose index number is the size of the switch variable (i.e. the starting address of the jump table + the size of the table item * index number). The program then jumps to this address for execution, and the jump of the branch is completed.

It can be seen that the above method also generates a table (a function pointer table), so the efficiency of this method is the same as that of switch case.

3 precautions for state machine application

The difficulty in the application of program scheduling mechanism based on state machine lies not in the understanding of the concept of state machine, but in the reasonable division of system working state.

Beginners often treat a "program action" as a "state", which I call "pseudo state". So how to distinguish between "action" and "state"? The craftsman's experience is to see the essence of the two: "action" is unstable. Even if there is no conditional trigger, "action" ends once it is executed; The "state" is relatively stable. If there is no trigger of external conditions, a state will continue all the time.

Another fatal mistake for beginners is to miss some states in state division, which I call "leaky states".

The existence of "pseudo state" and "leaky state" will lead to the laxity of program structure. Therefore, special care should be taken to avoid.

3 November 2021, 21:33 | Views: 3683

Add new comment

For adding a comment, please log in
or create account

0 comments