[comp.std.c] Is `char const *foo;' legal?

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