rfg@paris.ics.uci.edu (Ron Guilmette) (01/11/90)
I have recently learned that the GNU C compiler accepts the following
declaration without complaint:
char const *foo;
It treats such a declaration as being identical to:
const char *foo;
Now I have looked at the draft ANSI standard, and I can find no examples
that look like `<typename> const *<variable-name>;'.
Due to the fact that the C declaration syntax is so complex, I don't
even want to try to think about the issue of whether or not such declarations
are syntactically legal.
So let me just ask the general question: "Are such declarations both
syntactically and semantically legal?"
Please excuse me if this question seems excessively naive. It is just
that I have never before seen any declarations of this form.
One other question. If this form of declaration *is* legal, then
does the standard contain any verbage which would clarify the type of
`bar' in the following example?
void foo (char const bar[])
{
}
GCC accepts this declaration, and it binds the `const' with lower `priority'
that the `[]'. Thus, the type of `bar' is taken as pointer to constant char.
I have found no basis in the standard for either this binding *or* for the
other alternative (i.e. binding the `const' more tightly than the `[]').
Did I miss something? Which binding is "correct"? Why?
// rfg
srg@quick.COM (Spencer Garrett) (01/11/90)
In article <25ABBF93.9618@paris.ics.uci.edu>, rfg@paris.ics.uci.edu (Ron Guilmette) writes: > I have recently learned that the GNU C compiler accepts the following > declaration without complaint: > > char const *foo; > ... > So let me just ask the general question: "Are such declarations both > syntactically and semantically legal?" > ... > One other question. If this form of declaration *is* legal, then > does the standard contain any verbage which would clarify the type of > `bar' in the following example? > > void foo (char const bar[]) > { > } > > GCC accepts this declaration, and it binds the `const' with lower `priority' > that the `[]'. Thus, the type of `bar' is taken as pointer to constant char. Not only legal, but IMHO preferred. Think of "const" and "volatile" not as type names, but as *operators* (on a par with *) with the unusual characteristic of being allowed to float all the way to the left of the type names and storage-class indicators (which sometimes makes the declaration read better (in English)). Parentheses aside, they modify the declaration to their right, just like *. I prefer to write: char const *foo; to emphasize that "const *foo" is a char. When you take the * off to look at the named variable itself you have taken off the const keyword as well, so you know that the pointer isn't constant, just the chars. In the same way, you read char *bar[]; as an array of pointers, so char const bar[]; would be an array of const chars. Use in a parameter declaration implicitly turns "array of" into "pointer to" in either case. I hope this helps.
steve@groucho.ucar.edu (Steve Emmerson) (01/11/90)
Ron Guilmette, <rfg@paris.ics.uci.edu>, writes with regard to the following declaration: > char const *foo; >So let me just ask the general question: "Are such declarations both >syntactically and semantically legal?" I cannot speak on the standard since I don't have one. K&R-II, however indicates that the above is syntactically and semantically valid. The above string can be generated by the following sequence (cf. appendix A13): declaration declaration-specifiers init-declarator-list(opt) ";" storate-class-specifier declaration-specifiers(opt) init-declarator ";" "char" type-qualifier declaration-specifiers(opt) declarator ";" "char" "const" pointer(opt) direct-declarator ";" "char" "const" "*" type-qualifier-list(opt) identifier ";" "char" "const" "*" "foo" ";" The crucial grammar rule is declaration-specifiers: storage-class-specifier declaration-specifiers(opt) type-specifier declaration-specifiers(opt) type-qualifier declaration-specifiers(opt) which allows generation of both "const char" and "char const". Section A8.6.1 says that type-qualifies which follow the "*" in a pointer declaration apply to the pointer itself, rather than to the pointed-at object. Previous statements and examples about type-qualifiers -- in which they were placed before the "*" -- indicate that they apply to the pointed-at objects. [As an aside, it might be a good idea to obtain the book -- if you haven't already. Zot!] Steve Emmerson steve@unidata.ucar.edu ...!ncar!unidata!steve
meissner@osf.org (Michael Meissner) (01/11/90)
In article <25ABBF93.9618@paris.ics.uci.edu> rfg@paris.ics.uci.edu (Ron Guilmette) writes: | I have recently learned that the GNU C compiler accepts the following | declaration without complaint: | | char const *foo; | | It treats such a declaration as being identical to: | | const char *foo; | | Now I have looked at the draft ANSI standard, and I can find no examples | that look like `<typename> const *<variable-name>;'. | | Due to the fact that the C declaration syntax is so complex, I don't | even want to try to think about the issue of whether or not such declarations | are syntactically legal. | | So let me just ask the general question: "Are such declarations both | syntactically and semantically legal?" Yes. The reason you didn't see syntax for: <typename> const *<variable-name>; is because it would lead to a reduce/reduce conflict, since const and volatile are typenames. | Please excuse me if this question seems excessively naive. It is just | that I have never before seen any declarations of this form. | | One other question. If this form of declaration *is* legal, then | does the standard contain any verbage which would clarify the type of | `bar' in the following example? | | void foo (char const bar[]) | { | } | | GCC accepts this declaration, and it binds the `const' with lower `priority' | that the `[]'. Thus, the type of `bar' is taken as pointer to constant char. | | I have found no basis in the standard for either this binding *or* for the | other alternative (i.e. binding the `const' more tightly than the `[]'). | Did I miss something? Which binding is "correct"? Why? In the above example, const binds with char (ie, lower priority), since the typename goes to the innermost part of the declaration. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA Catproof is an oxymoron, Childproof is nearly so
walter@hpclwjm.HP.COM (Walter Murray) (01/13/90)
[Regarding a declaration like "const char bar[]"] [Description of how GCC interprets this] >| I have found no basis in the standard for either this binding *or* for the >| other alternative (i.e. binding the `const' more tightly than the `[]'). >| Did I miss something? Which binding is "correct"? Why? In this example, "bar" has type "array of const char". The const qualifier applies to the element type, not the array type. Here are relevant sections from the Standard (quoting from the 12/7/88 draft): The type of an array is defined by 3.5.4.2, page 68, lines 6-10. The inductive method used to define the type of a derived declarator can be a little confusing. See the paragraph in 3.5.4 beginning on page 66, line 45, for an explanation. Section 3.1.2.5, page 25, lines 22-23: "A derived type is not qualified by the qualifiers (if any) of the type from which it is derived." If you try to use a typedef to force the array type itself to be qualified, it won't work. Section 3.5.3, page 65, lines 23-25. Walter Murray ----------
gwyn@smoke.BRL.MIL (Doug Gwyn) (01/13/90)
In article <25ABBF93.9618@paris.ics.uci.edu> rfg@paris.ics.uci.edu (Ron Guilmette) writes: >Did I miss something? Which binding is "correct"? Why? "char const TOKENS" is equivalent to "const char TOKENS". If you want the "const" to qualify something within the "TOKENS" part, you have to wedge it into the "TOKENS".
rfg@ics.uci.edu (Ron Guilmette) (01/14/90)
In article <12570037@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes: >[Regarding a declaration like "const char bar[]"] ... >Here are relevant sections from the Standard (quoting from the 12/7/88 >draft): > >The type of an array is defined by 3.5.4.2, page 68, lines 6-10. >The inductive method used to define the type of a derived declarator >can be a little confusing... Yowza! // rfg