Follow me in c++ intermediate chapter - function pointer array

1. Array of function pointers

In the previous analysis of function pointers, in fact, this array of function pointers should be integrated into it, but the result was forgotten. What is a function pointer is basically understood now, so what is an array of function pointers? It is enough to define a set of arrays. In fact, it is a set of function pointers or put the function pointers in the array. The advantage of the function pointer array is that some similar actions can be concentrated in one module for operation, reducing related repetitive code operations and making the code clearer. But the shortcomings are also obvious. General function pointers are not as convenient to debug as ordinary functions, especially for novices, jumping around may be confusing for a while.
In some protocol analysis, data forwarding control, and switch statements, the use of function pointers can make the design more flexible and flexible, and will not cause changes in the entire design due to changes in code processing. Even if there are code changes, basically only increase to not fix. This greatly improves the overall security and robustness of the software.
With the array of function pointers, it has to be mentioned that the pointer to the array of function pointers is nothing, in fact, it is to take the pointer to the array of function pointers. Let's take a look at the example to make it clearer:

//array of function pointers
int* (*pf[2])(int * p);

//pointer to array of function pointers
int* (*(*pf)[2])(int * p);

For those who are more familiar with pointers, this is not a problem, but for those who are not familiar with it, it will be a big headache. Do not rush to see the following routine will be more clear.

2. Application examples

As the saying goes, before the code, there are no secrets, let's take a look at the specific routine:

int f1(int d)
{
    std::cout << "this is f1!" << std::endl;
    return d;
}

int f2(int d)
{
    std::cout << "this is f2!" << std::endl;
    return d;
}

int f3(int d)
{
    std::cout << "this is f3!" << std::endl;
    return d;
}


// array of function pointers 
int (*funca[3])(int) = { f1, f2, f3 };

//pointer to array of function pointers
int (*(* pfunca)[3])(int) = &funca;

void CallFuncArray()
{
    int r = 0;

    //Call the array of function pointers, either way
    std::cout << "start call func pointer array" << std::endl;
    r = (*funca[0])(1);    
    r = (*funca[1])(2);   
    r = (*funca[2])(3); 

    r = funca[0](1);
    r = funca[1](2);
    r = funca[2](3);

    //auto handle array of function pointers
    std::cout << "start call func pointer array: use auto" << std::endl;
    auto arrayp = funca;
    //auto arrayp = {f1,f2,f3};//error, auto only matches a single variable
    arrayp[0](1);

    //pointer to array of function pointers 
    std::cout << "start call func pointer array pointer" << std::endl;
    auto paf = &funca;
    auto paf1 = pfunca;

    r = (*paf)[0](1);
    r = (*paf)[1](2);
    r = (*paf)[2](3);

    r = (*(*paf)[0])(1);
    r = (*(*paf)[1])(2);
    r = (*(*paf)[2])(3);

    r = (*paf1)[0](1);
    r = (*paf1)[1](2);
    r = (*paf1)[2](3);
}

void do1(char *buf)
{
    std::cout << "this is do1!" << std::endl;
}

void do2(char *buf)
{
    std::cout << "this is do2!" << std::endl;
}
// function pointer array instance
void (*paEx[2])(char *) = { do1, do2 };
void PhraseData(int type, char* buf)
{
    //You can dynamically jump here
    paEx[type](buf);
}

int main()
{
    CallFuncArray();
    return 0;
}

If this usage is used in some scenarios, it is still very good, you can analyze it carefully. Of course, it is better to template this code, you can try it out.

3. Summary

One of the pain points of learning c/c++ is pointers. The flexibility of pointers is a headache for beginners, intermediate developers, and even some so-called advanced developers. This is also the place where this language has been criticized. Pointers point to and fro, and in the end no one may know whether he points to a function or a variable. And this kind of call, if there are no auxiliary security measures, the result must be a crash. The crash is not terrible, the terrible thing is that after the crash, no useful information is provided.
Therefore, in the design, it is necessary to implement some centralized decoupling processing as much as possible. If pointers are involved, some uses of pointers must be limited and judged, such as the processing of various types in the new standard, and the processing of data formats. Wait, try to keep the code as safe as possible. A knife is a good knife and must be used well.

Tags: C++ programming language

Posted by AdB on Sun, 04 Dec 2022 12:07:25 +1030