简体   繁体   中英

What is the difference between a declarator and a direct-declarator?

In The C Programming Language, 2nd Edition, by authors Brian W. Kernighan and Dennis M. Ritchie, they talk about declarators and direct-declarators . The discussion starts in the book on p. 122 with dcl and direct-dcl 's Will you please explain the difference between a declarator and a direct-declarator in and easy to understand way? What makes it direct ?

Also, on p.225

where the direct-declarator is an identifier or a parenthesized identifier. In particular, it must not achieve function type by means of a typedef.

It seems to me that declarators are the declaration of a variable or function. In "TD", the T part specifies its specifiers and types, and the D part specifies the identity, meaning the unique identification name of the variable or function. It has something to do with the language's grammar.

Are declarator s indirect since they are not specified as direct, as in direct-declarator ?

Even the second edition of K&R is more of historical interest these days than practical interest.

Nevertheless, the terms "declarator" and "direct declarator" continue in use in the current C language specification. The language spec describes the former this way:

Each declarator declares one identifier, and asserts that when an operand of the same form as the declarator appears in an expression, it designates a function or object with the scope, storage duration, and type indicated by the declaration specifiers.

(C17 6.7.6/2)

It follows that "declaration specifiers" are separate from "declarators". In fact, a declarator is the part of a declaration that specifies what is being declared.

"Direct declarators" is a subset of declarators. The "direct" is meant to contrast with "indirect", as in pointers. For example, given

int i;
int *p;

The i and *p and p are all syntactically declarators, but of those, only i and p are direct declarators. And only i and *p are full declarators, which are those that do not appear as part of another declarator (as declarator p does).

It gets more complicated than that -- for example, enclosing any declarator in parentheses yields a direct declarator, even if by itself, the original declarator is not a direct one.

Overall, this is a syntactic distinction that you probably don't need to worry too much about unless you are writing a parser for the C language. And if you are doing that, then you really need to be looking at the formal syntax descriptions.

Loosely speaking, a declarator is a complete declaration, while a direct declarator is either an identifier by itself or an identifier followed by [] (making it an array) or () (making a function or function pointer).

The complete definition of these terms can be found in the syntax for a declarator which can be found in section 6.7.6p1 of the C11 standard :

declarator:

  • pointer opt direct-declarator

direct-declarator:

  • identifier
  • ( declarator )
  • direct-declarator [ type-qualifier-list opt assignment-expression opt ]
  • direct-declarator [ static type-qualifier-list opt assignment-expression ]
  • direct-declarator [ type-qualifier-list static assignment-expression ]
  • direct-declarator [ type-qualifier-list opt * ]
  • direct-declarator ( parameter-type-list )
  • direct-declarator ( identifier-list opt )

pointer:

  • * type-qualifier-list opt
  • * type-qualifier-list opt pointer

type-qualifier-list:

  • type-qualifier
  • type-qualifier-list type-qualifier

parameter-type-list:

  • parameter-list
  • parameter-list , ...

parameter-list:

  • parameter-declaration
  • parameter-list , parameter-declaration

parameter-declaration:

  • declaration-specifiers declarator
  • declaration-specifiers abstract-declarator opt

The grammar needs a direct-declarator token to specify precedence. As it is, * foo [ 3 ] must be parsed as a declarator that is * followed by a direct-declarator that is foo [ 3 ] . If the grammar did not separate a declarator and a direct-declarator , it could be unclear whether this was * followed by foo [ 3 ] grouped together or was * foo grouped together followed by [ 3 ] .

The grammar says a declarator is:

  • pointer opt direct-declarator

where pointer is * followed by optional qualifiers (like const ) and direct-declarator is one of:

  • identifier
  • ( declarator )
  • direct-declarator [ type-qualifier-list opt assignment-expression opt ]
  • direct-declarator [ static type-qualifier-list opt assignment-expression ]
  • direct-declarator [ type-qualifier-list static assignment-expression ]
  • direct-declarator [ type-qualifier-list opt * ]
  • direct-declarator ( parameter-type-list )
  • direct-declarator ( identifier-list opt )

So, given * foo [ 3 ] , we must take this as a declarator with * for pointer and foo [ 3 ] for direct-declarator . There is no way to have * at the start of a direct-declarator . Thus, * foo [ 3 ] must declare an array of 3 pointers, not a pointer to an array of 3 elements.

If those options for declarator and direct-declarator were merged into a single grammar token, then the parsing would be ambiguous. You could parse it as * foo [ 3 ] being that * foo is a declarator followed by [ 3 ] , which is not what we desire.

The name is of no great significance; we merely need another name for the additional token. There are other examples of this in the C grammar. Notably, the expressions grammar starts with expression and then goes through a chain of assignment-expression , conditional-expression , logical-OR-expression , and so on. These have names associated with the operators they involve, until you get to primary-expression . That has some semantic similarity to direct-declarator , suggesting they are both named in the spirit of “okay, we got to the bottom of this grammar chain, here is the primary/direct token.”

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM