Complex Declaration | C Language

Today, I read the chapter 'Analysis of C language declarations' in "C Expert Programming", and finally understand how complex declarations in C language are parsed. Although there are almost no cases of using complex declarations when writing code, here is a record to deepen the understanding of C language declarations.

Declarative precedence rules

The following rules are from "C Expert Programming".

C language declaration precedence rules:

  • A. Declarations are read starting with their name and then in order of priority.
  • B. The priority from high to low is:
    • B1. The bracketed portion of the declaration.
    • B2. Postfix operator: brackets ()indicate that this is a function, and the return value of the function is xxx ; square brackets []indicate that this is an array, and the array contains xxx .
    • B3. Prefix operator: The asterisk *indicates a pointer to xxx .
  • C. If the const or volatile keyword is immediately followed by a type specifier (eg int, long, etc.), then it acts on the type specifier. In other cases, the const and volatile keywords act on the pointer asterisk immediately to the left of it.

Draw a magic declaration parsing loop by the above rules:
image

Example 1

See an example:char *(*next)();

Interpret it with the priority rules:
- Find its name, it's next , notice that the closest to next is *AND ()
- The B1 rule tells us that ()the priority is the highest, we take the things in parentheses as a whole, and through the B3 rule, we get next is a pointer to xxx
- consider what's outside the parentheses. To choose between *and (), B2 takes precedence over B3. So next is a pointer to a function whose return value is xxx
- then, process *, get next is a pointer to a function whose return value is a pointer, pointer to xxx
- and finally, process char, get next is A pointer to a function whose return value is a pointer to a char type .

To sum up the above results is: next is a pointer, it points to a function, the return value of the function is a pointer of type char .

Example 2

Example const char *str[10];:

  • find name, is str
  • Consider *the []optimization level of AND, which []takes precedence over *, so str is an array that contains 10 xxx
  • Then, process *, so str is an array that contains 10 pointers to xxx
  • Finally, according to the C rules, const charnext is an array that contains 10 pointers to const char types

If it is char * const str[10];:
- found name, is str
- processed [], so str is an array, it contains 10 xxx
- processed const, according to C rules const-modified *, then str is an array, it contains 10 const pointers to
xxx- Processing char, next is an array that contains 10 const pointers to char type

Example 3

Here's a more complicated example char *(* test[10])(int p):

  • name is test
  • The test is ()surrounded, the ()inside is processed first.
  • Combined [], test is an array of 10 xxx
  • Combined *, test is an array of 10 pointers to xxx
  • Handling ()external, combined (int p), test is an array of 10 pointers that point to a function that has parametersint p
  • Processing *, test is an array of 10 pointers, each of which points to a function that has parameters int pand returns a pointer
  • Processing char, test is an array of 10 pointers, each of which points to a function that has parameters int pand returns a pointer to a char type

typedef simplifies complex declarations

The function of a typedef is to introduce a new name for a type. When complex declarations are required, use typedefs to simplify declarations. A typical example is signal()the declaration of a prototype. signal()A prototype is a system call used to notify the runtime system that a "software interrupt" has occurred.

signal()The declaration is as follows: void (*signal(int sig, void(*func)(int)))(int);. Using the above statement analysis, it means the following:
void (*signal( ))(int);, signal is a function, it returns a function pointer, the function pointed to by the latter accepts an int parameter and returns void. signalThere are two parameters, one of which is of the same type as the return value: void (*func)(int).

The above declaration can be simplified using typedefs, let's use typedefs for the common part:

/*
 * 表示ptr_to_func是一个函数指针,指向一个参数为int,返回值为void的函数。
 */
typedef void (* ptr_to_func)(int);

/*
 * 表示signal是一个函数,它接受两个参数,一个是int,一个是ptr_to_func,返回值为ptr_to_func。
 */
ptr_to_func signal(int, ptr_to_func);

refer to

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325506024&siteId=291194637