Professor Zhou Ligong's hard work for several years, " Programming and Data Structure " and " Programming for AMetal Framework and Interface (I) " . After the publication of the book content, there was a learning boom in the electronics industry. Authorized by Professor Zhou Ligong, this public number has serialized the contents of the book "Programming and Data Structure" and is willing to share it.

The second chapter is programming technology, this article is 2.1.1 function pointer and 2.1.2 pointer function.

> > > >   2.1   Function pointer and pointer function

> > >   2.1.1   Function pointer

The pointer to the variable points to a piece of data, and the pointer points to a different variable, and the different data is taken. The compiled function is a piece of code, the system then allocates a storage space for the corresponding code, and the starting address (also known as the entry address) for storing the code is a pointer to the function, that is, jump to a certain one. The code of the address unit is executed. The function pointer points to a piece of code (ie, a function) that points to a different function and has different behavior.

Because the function name is a constant address, you can call the corresponding function by assigning the address of the function to the function pointer. Just like the array name, we use the name of the function itself, which returns the address of the function. When a function name appears in an expression, the compiler converts it to a pointer, which is similar to the behavior of an array variable name, implicitly fetching its address. That is, the function name directly corresponds to the address of the instruction code generated by the function in memory, so the function name can be directly assigned to the pointer to the function. Since the value of the function pointer can be changed, you can use the same function pointer to point to a different function. If there are the following definitions:

Int (*pf)(int); // What is the type of pf function pointer?

K&R, the inventor of the C language, explained this: "Because * is a pre-operator, its priority is lower than (). In order for the connection to proceed correctly, it is necessary to add parentheses." This is somewhat far-fetched. Explain to explain and instead confuse people. Because *, (), [] in the declaration are not operators, and the precedence of operators is defined elsewhere in the grammar rules. The details are as follows:

Int   (*pf) (int a); // pf is a pointer to

Int   (*pf)(int a) ; // pf is a pointer to a function of (int)

Int (*pf)(int a) ; // pf is a pointer to a function that returns an int (parameter is int)

That is, pf is a pointer to a function that returns an int, and the function it points to accepts an argument of type int. The "int (*)(int)" type name is interpreted as pointing to the type of pointer that returns an int function (parameter is int). If you add a typedef before the definition, for example:

Typedef int (*pf)(int a);

Before adding typedef, pf is a function pointer variable; after adding typedef, pf becomes a function pointer type. The customary way is to write the type name pf to PF. such as:

Typedef int (*PF)(int a);

Unlike other types of declarations, the declaration of a function pointer requires the use of the typedef keyword. In addition, the only difference between the declaration of a function pointer and the function prototype is that the function name is replaced by (*PF), and "*" here means "pointing to a function whose type is PF". Obviously, the function pointer variables pf1, pf2 can be defined with the PF type. such as:

PF pf1, pf2;

Although this statement is equivalent to:

Int (*pf1)(int a);

Int (*pf2)(int a);

But this kind of writing is harder to understand. Since a function pointer variable is a variable, its value can be changed, so you can use the same function pointer variable to point to a different function. Using function pointers must do the following:

● Get the address of the function, for example, pf = add, pf = sub;

• Declare a function pointer, for example, "int (*pf)(int, int);";

● Use function pointers to call functions, such as pf(5, 8), (*pf)(5, 8). Why is pf equivalent to (*pf)?

• One argument is that since pf is a function pointer, assuming pf points to the add() function, *pf is the function add, so the function is called with (*pf)(). Although this format doesn't look good, it gives a strong hint - the code is calling a function with a function pointer.

• Another way of saying this is that since the function name is a pointer to a function, the pointer to the function should behave similarly to the function name, so use pf() to call the function. Because this method of calling is simple and elegant, people are more willing to choose – the inner heart of human beings following the good feelings is irresistible.

Although they are logically conflicting, different genres have different perspectives, and tolerance of logically unspoken ideas is the hallmark of human thinking activities.

In a pocket calculator, it is often necessary to use various calculations such as addition, subtraction, multiplication and division, and although the calling method is the same, in the operation, it is necessary to decide to call a function supporting an algorithm according to the specific situation. If you use the direct invocation method shown in Figure 2.1(a), it is bound to form a dependency structure. The strategy will be affected by the details of the change. When using the function pointer interface as shown in Figure 2.1(b), the interface is inverted (or inverted). When this dependency structure is constructed, the details and strategies are dependent on the function pointer interface, disconnecting unwanted direct dependencies.

When the direct access abstraction into a function pointer inverts (or reverses) the dependent relationship, the high-level module no longer relies on the lower-level module. High-level modules rely on abstraction, an interface in the form of a function pointer, while the details depend on abstraction. pf() implements this interface, ie both rely on the function pointer interface. In C, you usually use function pointers to implement DIP (inverted dependencies) and disconnect unwanted direct dependencies. The service can be called by the function pointer (called code), and the service can also call back the user function through the function pointer. It is the same, but in the operation, it is necessary to decide to call a function that supports an algorithm according to the specific situation. If you use the direct invocation method shown in Figure 2.1(a), it is bound to form a dependency structure. The strategy will be affected by the details of the change. When using the function pointer interface as shown in Figure 2.1(b), the interface is inverted (or inverted). When this dependency structure is constructed, the details and strategies are dependent on the function pointer interface, disconnecting unwanted direct dependencies.

Figure 2.1 Inverting dependencies using function pointers

Function pointers are a powerful language capability that programmers often overlook, which not only makes the code more flexible and measurable, but also helps to eliminate duplicate conditional logic. It also saves the caller from compiling or linking. A particular function, which has the great advantage of reducing the coupling between C language modules. However, the use of function pointers is conditional. If the calling relationship between the calling function and the called function never changes, the direct calling method is the simplest. In this case, the coupling between modules is Reasonable, not only is the code simple and straightforward, but the overhead is also minimal. If you need to call a function with one or more function pointers at runtime, using function pointers is the best choice, usually called a dynamic interface. The sample program is detailed in Listing 2.1.

Program Listing 2.1 Calling Function Sample Programs via Function Pointers (1)

1   #include

2 int add(int a, int b)

3 {

4 printf("addition function");

5 return a + b;

6 }

7

8 int sub(int a, int b)

9 {

10 printf("subtration function");

11 return a - b;

12 }

13

14 int main(void)

15 {

16 int (*pf)(int, int);

17

18 pf = add;

19 printf("addition result:%d", pf(5, 8));

20 pf = sub;

21 printf("subtration result:%d", pf(8, 5));

22 return 0;

twenty three }

Since any data type pointer can assign a value to a void pointer variable, and the essence of the function pointer is an address, you can use this feature to define pf as a void * type pointer, then any pointer can be assigned to the void * type. Pointer variable. Its calling method is as follows:

Void * pf = add;

Printf("addition result:%d", ((int (*)(int, int)) pf)(5, 8));

During the use of the function pointer, the value of the pointer indicates the address that the program will jump to, and the type of the pointer indicates how the program is called. When calling a function with a function pointer, it is important to ensure that the type of the function being called is exactly the same as the type of the function pointed to, so the void * type must be converted to ((int (*)(int, int)) pf)), the type is "int (*)(int, int)".

> > >   2.1.2   Pointer function

In fact, pointer variables are very versatile, pointers can be used not only as arguments to functions, but pointers can also be used as return values ​​for functions. When the return value of a function is a pointer, then this function is a pointer function. When given a pointer to two integers, the function shown in Listing 2.2 returns a pointer to the larger of the two integers. When max is called, a pointer to two int type variables is used as a parameter, and the result is stored in a pointer variable, where the pointer returned by the max function is one of the two pointers passed in as arguments.

Program list   2.2   Find the maximum function (the pointer is the return value of the function)

1 #include

2 int *max(int ​​*p1, int *p2)

3 {

4 if(*p1 > *p2)

5 return p1;

6 else

7 return p2;

8 }

9

10 int main(int argc, char *argv[])

11 {

12 int *p, a, b;

13   a = 1; b = 2;

14 p = max(&a, &b);

15 printf("%d", *p);

16 return 0;

17 }

Of course, the function can also return a string, which is actually the address of the string, but be sure to pay attention to how to return a valid address. You can either return a static string address, or allocate a string of memory on the heap, and then return its address. Note that do not return the address of a local string because memory may be overwritten by other stack frames.

Let's take a look at it. What is the difference between a pointer function and a function pointer variable? If there are the following definitions:

Int *pf(int *, int); // int *(int *, int) type

Int (*pf)(int, int); // int (*)(int, int) type

Although there is only one parenthesis between the two, the meaning is quite different. The essence of a function pointer variable is a pointer variable, which points to a function; the essence of a pointer function is a function that declares pf as a function that takes two arguments, one of which is int * and the other is int. The return value is a pointer of type int.

In the pointer function, there is also a class of such a function whose return value is a pointer to a function. For beginners, let alone write such a function statement, it is also a fog to see such a way of writing. For example, the following statement:

Int (*   Ff (int) )(int, int); // ff is a function

Int ( * ff (int) )(int, int); // ff is a pointer function whose return value is a pointer

Int   (* ff (int))(int, int) ; //   The pointer points to a function

This kind of writing is really very difficult to understand, so that some beginners misunderstand that writing code that others can't understand can show their high level. In fact, on the contrary, the ability to write easy-to-understand code is a measure of whether a programmer is excellent. When typedef is used, PF becomes a function pointer type. which is:

Typedef int (*PF)(int, int);

With this type, the declaration of the above function becomes much simpler. which is:

PF ff(int);

The following uses program listing 2.3 as an example to illustrate the use of function pointers as function return values. When the user inputs d, x, and p, respectively, the maximum, minimum, and average values ​​of the array are obtained.

Listing 2.3 Finding the best value and average sample program

1 #include

2 #include

3 double getMin(double *dbData, int iSize) //   Find the minimum

4 {

5 double dbMin;

6

7 assert((dbData != NULL) && (iSize > 0));

8 dbMin = dbData[0];

9 for (int i = 1; i < iSize; i++){

10 if (dbMin > dbData[i]){

11 dbMin = dbData[i];

12 }

13 }

14 return dbMin;

15 }

16

17 double getMax(double *dbData, int iSize) //   Find the maximum

18 {

19 double dbMax;

20

21 assert((dbData != NULL) && (iSize > 0));

22 dbMax = dbData[0];

23 for (int i = 1; i < iSize; i++){

24 if (dbMax < dbData[i]){

25 dbMax = dbData[i];

26 }

27 }

28 return dbMax;

29 }

30

31 double getAverage(double *dbData, int iSize) //   Average

32 {

33 double dbSum = 0;

34

35 assert((dbData != NULL) && (iSize > 0));

36 for (int i = 0; i < iSize; i++){

37 dbSum += dbData[i];

38 }

39 return dbSum/iSize;

40 }

41

42 double unKnown(double *dbData, int iSize) //   Unknown algorithm

43 {

44 return 0;

45 }

46

47 typede double (*PF)(double *dbData, int iSize); //   Define function pointer type

48 PF getOperation(char c) //   Get the operation pointer based on the character, return the function pointer

49 {

50 switch (c){

51 case 'd':

52 return getMax;

53 case 'x':

54 return getMin;

55 case 'p':

56 return getAverage;

57 default:

58 return unKnown;

59 }

60 }

61

62 int main(void)

63 {

64 double dbData[] = {3.1415926, 1.4142, -0.5, 999, -313, 365};

65 int iSize = sizeof(dbData) / sizeof(dbData[0]);

66 char c;

67

68 printf("Please input the Operation :");

69 c = getchar();

70 PF pf = getOperation(c);

71 printf("result is %lf", pf(dbData, iSize));

72 return 0;

73 }

The first four functions respectively implement the maximum, minimum, average, and unknown algorithms. The return value obtained by getOperation() according to the input character is returned in the form of a function pointer. From pf(dbData, iSize), it can be seen that Call the function through this pointer. Note that the pointer function can return the new memory address, the address of the global variable, and the address of the static variable, but can not return the address of the local variable, because after the function ends, the declaration period of the declared local variable inside the function has ended, the memory will Give up automatically. Obviously, accessing the data pointed to by this pointer in the calling function will produce unpredictable results.

If you want to learn more embedded courses, please scan the QR code below and learn now!

Arts And Crafts Casting

Arts And Crafts Casting,Hpdc Die Casting,Aluminum Die Casting Air,Die Casting Aluminium Alloys

Dongguan Metalwork Technology Co., LTD. , https://www.diecast-pro.com