|
Analyze and digest this information:
Excerpts from others:
All complex pointer declarations in C language are composed of various nested declarations. How to interpret complex pointer declarations? The right-left rule is a well-known and commonly used method. However, the right-left rule is not actually the content of the C standard, it is a method summed up from the declaration requirements of the C standard. The declaration rules of the C standard are used to solve how to create a declaration, while the right-left rule is used to solve how to identify a declaration. The two can be said to be opposite. The original English text of the right-left rule says:
The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.
The English translation of this paragraph is as follows:
Right-Left Rule: First look at the innermost parenthesis, then look to the right, then to the left. Whenever you encounter parentheses, you should switch your reading direction. Once you have parsed everything inside the parentheses, jump out of the parentheses. Repeat this process until the entire statement is resolved.
The author wants to make a small amendment to this rule. It should start reading from undefined identifiers, not from parentheses. The reason for undefined identifiers is that there may be multiple identifiers in a declaration. , But there will only be one undefined identifier.
Now discuss the application of the right-left rule through some examples, starting with the simplest and gradually deepening:
int (*func)(int *p);
First find the undefined identifier, which is func. There is a pair of parentheses on the outside and an * sign on the left, which shows that func is a pointer, and then jump out of the parentheses. Look at the right side first. It is also a parenthesis. Explain that (*func) is a function, and func is a pointer to this type of function, which is a function pointer. This type of function has formal parameters of type int*, and the return value type is int.
int (*func)(int *p, int (*f)(int*));
func is enclosed by a pair of parentheses, and there is a * sign on the left, indicating that func is a pointer, out of the parentheses, and there is also a parenthesis on the right, then func is a pointer to a function. Such functions have int * and int (*)(int *) Such a parameter, the return value is of type int. Let's take a look at func's formal parameter int (*f)(int*). Similar to the previous explanation, f is also a function pointer. The function pointed to has a parameter of type int* and the return value is int.
int (*func[5])(int *p);
On the right side of func is an operator [], indicating that func is an array with 5 elements, and there is a * on the left of func, indicating that the elements of func are pointers. Note that the * is not a modification of func, but a modification of func[5 ], the reason is that the [] operator has a higher priority than *, and func is combined with [] first, so * modifies func[5]. Jump out of this bracket and look at the right side. There is also a pair of parentheses, indicating that the elements of the func array are pointers to function types. The function it points to has formal parameters of type int* and the return value type is int.
int (*(*func)[5])(int *p);
func is enclosed by a parenthesis, and there is another * on the left, then func is a pointer, jump out of the parentheses, and on the right is an arithmetic symbol [], indicating that func is a pointer to an array. Now look to the left, there is an * on the left, Explain that the elements of this array are pointers, and then jump out of the brackets, and there is another bracket on the right, indicating that the elements of this array are pointers to functions. To sum up, it is: func is a pointer to an array, and the elements of this array are function pointers. These pointers point to functions with int* formal parameters and return values of type int.
int (*(*func)(int *p))[5];
func is a function pointer. This type of function has int* type parameters. The return value is a pointer to an array. The element of the pointed-to array is an array with 5 int elements.
Note that some complex pointer declarations are illegal, for example:
int func(void) [5];
func is a function that returns an array with 5 int elements. But the C language function return value cannot be an array, this is because if the function return value is allowed to be an array, then the thing that receives the contents of this array must also be an array, but the C language array name is an rvalue, it cannot Receive another array as an lvalue, so the function return value cannot be an array.
int func[5](void);
func is an array with 5 elements. The elements of this array are functions. This is also illegal, because in addition to the elements of the array must be the same type, the memory space occupied by each element must also be the same. Obviously, the function cannot meet this requirement. Even if the type of the function is the same, the space occupied by the function is usually not the same.
As an exercise, here are a few complex pointer declarations for the reader to parse. The answer is in Chapter 10.
int (*(*func)[5][6])[7][8];
int (*(*(*func)(int *))[5])(int *);
int (*(*func[7][8][9])(int*))[5];
In practice, when a complex pointer needs to be declared, if the entire declaration is written in the form shown above, the readability of the program will be greatly damaged. Typedefs should be used to decompose declarations layer by layer to enhance readability. For example, for declarations:
int (*(*func)(int *p))[5];
It can be broken down like this:
typedef int (*PARA)[5];
typedef PARA (*func)(int *);
This makes it easier to see. |
|