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-liststatic
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 pointertype-qualifier-list:
- type-qualifier
- type-qualifier-list type-qualifier
parameter-type-list:
- parameter-list
- parameter-list
,
...
parameter-list:
- parameter-declaration
- parameter-list
,
parameter-declarationparameter-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:
where pointer is *
followed by optional qualifiers (like const
) and direct-declarator is one of:
(
declarator )
[
type-qualifier-list opt assignment-expression opt ]
[
static
type-qualifier-list opt assignment-expression ]
[
type-qualifier-list static
assignment-expression ]
[
type-qualifier-list opt * ]
(
parameter-type-list )
(
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.