Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102748 > unrolled thread
| Started by | BartC <bc@freeuk.com> |
|---|---|
| First post | 2017-01-30 13:00 +0000 |
| Last post | 2017-03-06 11:27 -0800 |
| Articles | 20 on this page of 38 — 11 participants |
Back to article view | Back to comp.lang.c
C declarations BartC <bc@freeuk.com> - 2017-01-30 13:00 +0000
Re: C declarations David Brown <david.brown@hesbynett.no> - 2017-01-30 14:25 +0100
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-01-30 11:42 -0800
Re: C declarations Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-01-31 13:46 -0800
Re: C declarations BartC <bc@freeuk.com> - 2017-01-31 22:13 +0000
Re: C declarations Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-01-31 16:43 -0800
Re: C declarations Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-01-31 17:06 -0800
Re: C declarations Ian Collins <ian-news@hotmail.com> - 2017-02-01 17:58 +1300
Re: C declarations luser droog <luser.droog@gmail.com> - 2017-01-31 22:42 -0800
Re: C declarations Ian Collins <ian-news@hotmail.com> - 2017-02-01 19:48 +1300
Re: C declarations Robert Wessel <robertwessel2@yahoo.com> - 2017-02-01 01:18 -0600
Re: C declarations David Brown <david.brown@hesbynett.no> - 2017-02-01 10:10 +0100
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 11:39 +0000
Re: C declarations David Brown <david.brown@hesbynett.no> - 2017-02-01 13:55 +0100
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 13:22 +0000
Re: C declarations David Brown <david.brown@hesbynett.no> - 2017-02-01 16:30 +0100
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-02-01 08:15 -0800
Re: C declarations supercat@casperkitty.com - 2017-02-01 08:44 -0800
Re: C declarations David Brown <david.brown@hesbynett.no> - 2017-02-01 20:56 +0100
Re: C declarations supercat@casperkitty.com - 2017-02-01 08:29 -0800
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 17:24 +0000
Re: C declarations fir <profesor.fir@gmail.com> - 2017-02-01 09:55 -0800
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 18:44 +0000
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-02-01 11:03 -0800
Re: C declarations fir <profesor.fir@gmail.com> - 2017-02-01 12:26 -0800
Re: C declarations fir <profesor.fir@gmail.com> - 2017-02-01 13:03 -0800
Re: C declarations fir <profesor.fir@gmail.com> - 2017-02-01 13:12 -0800
Re: C declarations fir <profesor.fir@gmail.com> - 2017-02-03 16:07 -0800
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-02-01 10:44 -0800
Re: C declarations jameskuyper@verizon.net - 2017-02-01 11:08 -0800
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-02-01 10:40 -0800
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 17:04 +0000
Re: C declarations Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-01 19:58 +0000
Re: C declarations BartC <bc@freeuk.com> - 2017-02-01 21:23 +0000
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-02-01 08:08 -0800
Re: C declarations Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-02-01 12:45 -0800
Re: C declarations Andrey Tarasevich <andreytarasevich@hotmail.com> - 2017-03-06 11:19 -0800
Re: C declarations Keith Thompson <kst-u@mib.org> - 2017-03-06 11:27 -0800
Page 1 of 2 [1] 2 Next page →
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-01-30 13:00 +0000 |
| Subject | C declarations |
| Message-ID | <o6nd9u$rp1$1@dont-email.me> |
I've been studying C's syntax in a bit more detail and trying to match
up what a compiler allows, with the grammar. Here's one example:
#include <stdio.h>
a=10, b=20, c=30;
int main(void){}
This compiles fine. But not if the declarations are inside a function. I
can't see where this is specified in the grammar at the back of K&R2,
which only seems to allow a default type-specifier when a is a function
definition (and '=10', b, c and the rest wouldn't be allowed). With the
2011 version in the standard, it isn't allowed at all that I can see.
Then there is this, also outside a function, although more compilers
complain about it:
*p = 10;
This presumably declares p to be of type int*, and initialises it to 10.
Furthermore, I can write:
*p = 10; // outside a function
and: *p = 10; // inside a function
and that will compile (although fewer compilers accept it), using the
same 'p', but do different things.
If writing a C parser, does one need to accommodate all this stuff or
not? *p probably be dispensed with, and maybe a=10 too. But I think
implicit return types for functions still crop up. And they /could/ be
written like this:
((((main())))){};
but not like this:
((((main(()))))){};
as it's an error!
--
bartc
[toc] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-01-30 14:25 +0100 |
| Message-ID | <o6nepi$1l5$1@dont-email.me> |
| In reply to | #102748 |
On 30/01/17 14:00, BartC wrote:
> I've been studying C's syntax in a bit more detail and trying to match
> up what a compiler allows, with the grammar. Here's one example:
>
> #include <stdio.h>
>
> a=10, b=20, c=30;
>
> int main(void){}
>
> This compiles fine.
By "compiles fine", you mean when you ask the compiler to use a 25 year
old standard and specifically disable default warning messages?
Yes, this is legal in C90 and before. It is usually considered bad
code, but it is legal AFAIK.
> But not if the declarations are inside a function. I
> can't see where this is specified in the grammar at the back of K&R2,
> which only seems to allow a default type-specifier when a is a function
> definition (and '=10', b, c and the rest wouldn't be allowed). With the
> 2011 version in the standard, it isn't allowed at all that I can see.
"Implicit int" was dropped in C99, in all cases.
In C90, you need /something/ to tell the compiler that "a = 10;" is a
definition and not just using an external symbol. You can do that with
a type "int a = 10;", or with "auto a = 10;" or "register a = 10;", both
of which make the type "int" by default.
>
> Then there is this, also outside a function, although more compilers
> complain about it:
>
> *p = 10;
>
> This presumably declares p to be of type int*, and initialises it to 10.
Again, I believe it is legal syntax in C90. It has undefined behaviour
(due to the conversion from an integer).
>
> Furthermore, I can write:
>
> *p = 10; // outside a function
> and: *p = 10; // inside a function
>
> and that will compile (although fewer compilers accept it), using the
> same 'p', but do different things.
When you put "*p = 10;" as a declaration, you are initialising "p" to
10. When you write "*p = 10;" as a statement, it is assigning 10 to the
int pointed to by p.
The standards committee were doing the right thing when they killed off
"implicit int" in C99 !
>
> If writing a C parser, does one need to accommodate all this stuff or
> not? *p probably be dispensed with, and maybe a=10 too. But I think
> implicit return types for functions still crop up. And they /could/ be
> written like this:
>
> ((((main())))){};
>
> but not like this:
>
> ((((main(()))))){};
>
> as it's an error!
>
If you are writing a C parser today, you might want to make it C99 and
C11, and disregard C90 or before. A good deal of C90 code is also
perfectly valid C99 code - certainly all the C90 code I have written
would be fine as C99. And I think the key reason for writing C90 (also
known, slightly inaccurately, as "ANSI C") today is for portability -
that includes portability to C99 compilers.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-01-30 11:42 -0800 |
| Message-ID | <lnwpdc9vwe.fsf@kst-u.example.com> |
| In reply to | #102753 |
David Brown <david.brown@hesbynett.no> writes:
> On 30/01/17 14:00, BartC wrote:
[...]
>> Then there is this, also outside a function, although more compilers
>> complain about it:
>>
>> *p = 10;
>>
>> This presumably declares p to be of type int*, and initialises it to 10.
>
> Again, I believe it is legal syntax in C90. It has undefined behaviour
> (due to the conversion from an integer).
I believe it's legal syntax, but it's a constraint violation. There is
no implicit conversion from int to int* (other than the special case of
a null pointer constant).
Pre-ANSI C compilers commonly permitted implicit conversions between
pointers and integers, but C89/C90 did not.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-01-31 13:46 -0800 |
| Message-ID | <o6r0gj$4di$1@dont-email.me> |
| In reply to | #102748 |
On 1/30/2017 5:00 AM, BartC wrote:
> I've been studying C's syntax in a bit more detail and trying to match
> up what a compiler allows, with the grammar. Here's one example:
>
> #include <stdio.h>
>
> a=10, b=20, c=30;
>
> int main(void){}
>
> This compiles fine.
I can't say for sure if this was OK in K&R, but in the standard C (even
in the first C89/90) this is already illegal. The grammar for
_declaration_ requires at least a storage class specifier, a
type-specifier or a type qualifier to be present. Which means that if
you wanted to take advantage of the "implicit int" rule in C89/90, you'd
have to do at least
static a = 10, b = 20, c = 30;
or, say,
const a = 10, b = 20, c = 30;
What you have in your original code is not compliant with C89/90
requirements.
> But not if the declarations are inside a function.
The requirements are the same for local declarations. There should be no
difference in this specific regard.
> Then there is this, also outside a function, although more compilers
> complain about it:
>
> *p = 10;
>
> This presumably declares p to be of type int*, and initialises it to 10.
Same thing. In C89/90 you'd need at least something like
static *p = 0;
(and, of course, your `10` is not a legal initializer for a pointer).
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-01-31 22:13 +0000 |
| Message-ID | <o6r22b$ab3$1@dont-email.me> |
| In reply to | #102880 |
On 31/01/2017 21:46, Andrey Tarasevich wrote:
> On 1/30/2017 5:00 AM, BartC wrote:
>> I've been studying C's syntax in a bit more detail and trying to match
>> up what a compiler allows, with the grammar. Here's one example:
>>
>> #include <stdio.h>
>>
>> a=10, b=20, c=30;
>>
>> int main(void){}
>>
>> This compiles fine.
>
> I can't say for sure if this was OK in K&R, but in the standard C (even
> in the first C89/90) this is already illegal. The grammar for
> _declaration_ requires at least a storage class specifier, a
> type-specifier or a type qualifier to be present. Which means that if
> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
> have to do at least
>
> static a = 10, b = 20, c = 30;
>
> or, say,
>
> const a = 10, b = 20, c = 30;
>
> What you have in your original code is not compliant with C89/90
> requirements.
Out of six compilers, three gave a warning about an implicit int, the
other three said nothing at all. That doesn't suggest to me that they
consider there to be anything much wrong with it.
>
>> But not if the declarations are inside a function.
>
> The requirements are the same for local declarations. There should be no
> difference in this specific regard.
All six compilers report an error (not a warning) when the same code is
inside a function. (Undeclared identifier.)
But then, in a function, a=10 looks like an assignment. Outside, it
can't be an assignment.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-01-31 16:43 -0800 |
| Message-ID | <o6ras7$845$1@dont-email.me> |
| In reply to | #102885 |
On 1/31/2017 2:13 PM, BartC wrote:
>>
>> I can't say for sure if this was OK in K&R, but in the standard C (even
>> in the first C89/90) this is already illegal. The grammar for
>> _declaration_ requires at least a storage class specifier, a
>> type-specifier or a type qualifier to be present. Which means that if
>> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
>> have to do at least
>>
>> static a = 10, b = 20, c = 30;
>>
>> or, say,
>>
>> const a = 10, b = 20, c = 30;
>>
>> What you have in your original code is not compliant with C89/90
>> requirements.
>
> Out of six compilers, three gave a warning about an implicit int,
It is already perfectly enough. With C compilers, it is generally your
responsibility to tell "mere warnings" from "warnings" that indicate
constraint violations (i.e. "errors").
> the
> other three said nothing at all. That doesn't suggest to me that they
> consider there to be anything much wrong with it.
I wonder what those compilers might be.
I quick experiment with GCC and Clang in `-pedantic-errors` mode shows
them to report an error
error: data definition has no type or storage class
and
error: declaration specifier missing, defaulting to 'int'
respectively.
I was unable to force MSVC to generate an "error", but their warning
message was clear
warning C4218: nonstandard extension used: must specify at least a
storage class or a type
> All six compilers report an error (not a warning) when the same code is
> inside a function. (Undeclared identifier.)
Distinction between "errors" and "warnings" says absolutely nothing
about the validity of the code in such compilers as GCC and Clang. You
have to use `-pedantic-errors` mode to make these compilers to report
all constraint-violation-related "warnings" (and only such "warnings")
as "errors". It is still not perfect, but it works most of the time.
As you already noticed, most C compilers in existence would allow you to do
int *p = 10;
That does not mean that this is a valid C initialization.
These compilers are still trying to be compatible with legacy K&R code.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2017-01-31 17:06 -0800 |
| Message-ID | <o6rc79$bpg$1@dont-email.me> |
| In reply to | #102890 |
On 1/31/2017 4:43 PM, Andrey Tarasevich wrote:
>
> These compilers are still trying to be compatible with legacy K&R code.
>
The C89/90 grammar says
declaration:
declaration-specifiers init-declarator-list[opt];
declaration-specifiers:
storage-class-specifier declaration-specifiers[opt]
type-specifier declaration-specifiers[opt]
type-qualifier declaration-specifiers[opt]
and then
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name
This leaves no possibility of having an empty set of
'declaration-specifers'. In this grammar there's no way do derive a lone
'a = 10;' in the middle of the file .
Later in the text it says
"Each list of type specifiers shall be one of the following sets:
...
- int, signed, signed int, or no type specifiers
..."
But even tough it says "or no type specifiers", this does not override
the requirements of the grammar. The "no type specifiers" part simply
means that the set of 'type-specifier' sequence can be empty if
'storage-class-specifier' or 'type-qualifier' is present.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2017-02-01 17:58 +1300 |
| Message-ID | <efd881FhgsiU1@mid.individual.net> |
| In reply to | #102885 |
On 02/ 1/17 11:13 AM, BartC wrote:
> On 31/01/2017 21:46, Andrey Tarasevich wrote:
>> On 1/30/2017 5:00 AM, BartC wrote:
>>> I've been studying C's syntax in a bit more detail and trying to match
>>> up what a compiler allows, with the grammar. Here's one example:
>>>
>>> #include <stdio.h>
>>>
>>> a=10, b=20, c=30;
>>>
>>> int main(void){}
>>>
>>> This compiles fine.
>>
>> I can't say for sure if this was OK in K&R, but in the standard C (even
>> in the first C89/90) this is already illegal. The grammar for
>> _declaration_ requires at least a storage class specifier, a
>> type-specifier or a type qualifier to be present. Which means that if
>> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
>> have to do at least
>>
>> static a = 10, b = 20, c = 30;
>>
>> or, say,
>>
>> const a = 10, b = 20, c = 30;
>>
>> What you have in your original code is not compliant with C89/90
>> requirements.
>
> Out of six compilers, three gave a warning about an implicit int, the
> other three said nothing at all.
Care to name and shame?
--
Ian
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2017-01-31 22:42 -0800 |
| Message-ID | <3fd6c360-cd60-4d22-b7c6-4ac75ab206c3@googlegroups.com> |
| In reply to | #102893 |
On Tuesday, January 31, 2017 at 10:58:49 PM UTC-6, Ian Collins wrote:
> On 02/ 1/17 11:13 AM, BartC wrote:
> > On 31/01/2017 21:46, Andrey Tarasevich wrote:
> >> On 1/30/2017 5:00 AM, BartC wrote:
> >>> I've been studying C's syntax in a bit more detail and trying to match
> >>> up what a compiler allows, with the grammar. Here's one example:
> >>>
> >>> #include <stdio.h>
> >>>
> >>> a=10, b=20, c=30;
> >>>
> >>> int main(void){}
> >>>
> >>> This compiles fine.
> >>
> >> I can't say for sure if this was OK in K&R, but in the standard C (even
> >> in the first C89/90) this is already illegal. The grammar for
> >> _declaration_ requires at least a storage class specifier, a
> >> type-specifier or a type qualifier to be present. Which means that if
> >> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
> >> have to do at least
> >>
> >> static a = 10, b = 20, c = 30;
> >>
> >> or, say,
> >>
> >> const a = 10, b = 20, c = 30;
> >>
> >> What you have in your original code is not compliant with C89/90
> >> requirements.
> >
> > Out of six compilers, three gave a warning about an implicit int, the
> > other three said nothing at all.
>
> Care to name and shame?
>
I think we can all see the whodunit that the compilers
were almost certainly invoked in a (default) mode
which does not purport to be strictly standards-conforming.
--
wrench library col mustard
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2017-02-01 19:48 +1300 |
| Message-ID | <efdemaFhgsiU2@mid.individual.net> |
| In reply to | #102895 |
On 02/ 1/17 07:42 PM, luser droog wrote:
> On Tuesday, January 31, 2017 at 10:58:49 PM UTC-6, Ian Collins wrote:
>> On 02/ 1/17 11:13 AM, BartC wrote:
>>> On 31/01/2017 21:46, Andrey Tarasevich wrote:
>>>> On 1/30/2017 5:00 AM, BartC wrote:
>>>>> I've been studying C's syntax in a bit more detail and trying to match
>>>>> up what a compiler allows, with the grammar. Here's one example:
>>>>>
>>>>> #include <stdio.h>
>>>>>
>>>>> a=10, b=20, c=30;
>>>>>
>>>>> int main(void){}
>>>>>
>>>>> This compiles fine.
>>>>
>>>> I can't say for sure if this was OK in K&R, but in the standard C (even
>>>> in the first C89/90) this is already illegal. The grammar for
>>>> _declaration_ requires at least a storage class specifier, a
>>>> type-specifier or a type qualifier to be present. Which means that if
>>>> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
>>>> have to do at least
>>>>
>>>> static a = 10, b = 20, c = 30;
>>>>
>>>> or, say,
>>>>
>>>> const a = 10, b = 20, c = 30;
>>>>
>>>> What you have in your original code is not compliant with C89/90
>>>> requirements.
>>>
>>> Out of six compilers, three gave a warning about an implicit int, the
>>> other three said nothing at all.
>>
>> Care to name and shame?
>>
>
> I think we can all see the whodunit that the compilers
> were almost certainly invoked in a (default) mode
> which does not purport to be strictly standards-conforming.
Even unadorned gcc complains...
--
Ian
[toc] | [prev] | [next] | [standalone]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-02-01 01:18 -0600 |
| Message-ID | <eg239cd8il53hh3i99bdjs1a2mv78d70pl@4ax.com> |
| In reply to | #102896 |
On Wed, 1 Feb 2017 19:48:42 +1300, Ian Collins <ian-news@hotmail.com>
wrote:
>On 02/ 1/17 07:42 PM, luser droog wrote:
>> On Tuesday, January 31, 2017 at 10:58:49 PM UTC-6, Ian Collins wrote:
>>> On 02/ 1/17 11:13 AM, BartC wrote:
>>>> On 31/01/2017 21:46, Andrey Tarasevich wrote:
>>>>> On 1/30/2017 5:00 AM, BartC wrote:
>>>>>> I've been studying C's syntax in a bit more detail and trying to match
>>>>>> up what a compiler allows, with the grammar. Here's one example:
>>>>>>
>>>>>> #include <stdio.h>
>>>>>>
>>>>>> a=10, b=20, c=30;
>>>>>>
>>>>>> int main(void){}
>>>>>>
>>>>>> This compiles fine.
>>>>>
>>>>> I can't say for sure if this was OK in K&R, but in the standard C (even
>>>>> in the first C89/90) this is already illegal. The grammar for
>>>>> _declaration_ requires at least a storage class specifier, a
>>>>> type-specifier or a type qualifier to be present. Which means that if
>>>>> you wanted to take advantage of the "implicit int" rule in C89/90, you'd
>>>>> have to do at least
>>>>>
>>>>> static a = 10, b = 20, c = 30;
>>>>>
>>>>> or, say,
>>>>>
>>>>> const a = 10, b = 20, c = 30;
>>>>>
>>>>> What you have in your original code is not compliant with C89/90
>>>>> requirements.
>>>>
>>>> Out of six compilers, three gave a warning about an implicit int, the
>>>> other three said nothing at all.
>>>
>>> Care to name and shame?
>>>
>>
>> I think we can all see the whodunit that the compilers
>> were almost certainly invoked in a (default) mode
>> which does not purport to be strictly standards-conforming.
>
>Even unadorned gcc complains...
FWIW, MS VS2010 complains at higher warning levels (but not by
default). Accepting that form appears to date back to at least MSC
5.1 (circa 1988), so I'd guess a default extension* that's been left
enabled for compatibility.
*Or at least now it's an extension, harder to say what to call it in
1988.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-01 10:10 +0100 |
| Message-ID | <o6s8i9$cuj$1@dont-email.me> |
| In reply to | #102896 |
On 01/02/17 07:48, Ian Collins wrote:
> On 02/ 1/17 07:42 PM, luser droog wrote:
>> On Tuesday, January 31, 2017 at 10:58:49 PM UTC-6, Ian Collins wrote:
>>> On 02/ 1/17 11:13 AM, BartC wrote:
>>>> On 31/01/2017 21:46, Andrey Tarasevich wrote:
>>>>> On 1/30/2017 5:00 AM, BartC wrote:
>>>>>> I've been studying C's syntax in a bit more detail and trying to
>>>>>> match
>>>>>> up what a compiler allows, with the grammar. Here's one example:
>>>>>>
>>>>>> #include <stdio.h>
>>>>>>
>>>>>> a=10, b=20, c=30;
>>>>>>
>>>>>> int main(void){}
>>>>>>
>>>>>> This compiles fine.
>>>>>
>>>>> I can't say for sure if this was OK in K&R, but in the standard C
>>>>> (even
>>>>> in the first C89/90) this is already illegal. The grammar for
>>>>> _declaration_ requires at least a storage class specifier, a
>>>>> type-specifier or a type qualifier to be present. Which means that if
>>>>> you wanted to take advantage of the "implicit int" rule in C89/90,
>>>>> you'd
>>>>> have to do at least
>>>>>
>>>>> static a = 10, b = 20, c = 30;
>>>>>
>>>>> or, say,
>>>>>
>>>>> const a = 10, b = 20, c = 30;
>>>>>
>>>>> What you have in your original code is not compliant with C89/90
>>>>> requirements.
>>>>
>>>> Out of six compilers, three gave a warning about an implicit int, the
>>>> other three said nothing at all.
>>>
>>> Care to name and shame?
>>>
>>
>> I think we can all see the whodunit that the compilers
>> were almost certainly invoked in a (default) mode
>> which does not purport to be strictly standards-conforming.
>
> Even unadorned gcc complains...
>
It all depends on what Bart means by "compiles fine". Unadorned gcc
will happily compile:
a = 10, b = 20, c = 30;
int main(void) { }
It /will/ give a warning "data definition has no type or storage class",
but it will compile the code just as though the missing "int" was there.
I can't find any way to turn off the warning, which is probably a good
thing.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-01 11:39 +0000 |
| Message-ID | <o6sha6$a6l$1@dont-email.me> |
| In reply to | #102899 |
On 01/02/2017 09:10, David Brown wrote:
> On 01/02/17 07:48, Ian Collins wrote:
>>>> Care to name and shame?
The ones that gave warnings without any extra options were Pelles C,
lccwin, and gcc. The other three that said nothing nothing were DMC,
Tiny C and MSVC-2008.
>> Even unadorned gcc complains...
It doesn't complain very strongly. I couldn't see from the grammar of
any C version that 'a=10;' was legal outside of a function.
> It all depends on what Bart means by "compiles fine". Unadorned gcc
> will happily compile:
>
> a = 10, b = 20, c = 30;
>
> int main(void) { }
>
> It /will/ give a warning "data definition has no type or storage class",
> but it will compile the code just as though the missing "int" was there.
> I can't find any way to turn off the warning, which is probably a good
> thing.
The problem is this, if you are trying to implement such a parser: do
you deal with this strictly according to the grammar (and disallow it
completely)? That sounds a good idea, but then it will reject code that
will be passed by most other compilers with little problem.
However, the grammar also seems to allow these:
const const const a; // no initial value
int int int b;
gcc allows the first (but 'implicit int'), and disallows the second
(more than one type specifier).
(It seems crazy to me that a grammar could be so sloppy and ambiguous,
requiring masses of notes to clarify what is legal and what isn't. And I
couldn't even find the notes pertaining to the int int int; I have to
rely on trial and error using a well-regarded compiler (gcc).
It's so easy to get right. Although C's untidy scheme where 'int' and
'long' are both independent type-specs, but 'long' can also be a
modifier to 'int', doesn't help. And 'int static const unsigned const
long const long volatile' is legal... What a language!)
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-01 13:55 +0100 |
| Message-ID | <o6slob$pkf$1@dont-email.me> |
| In reply to | #102901 |
On 01/02/17 12:39, BartC wrote:
> On 01/02/2017 09:10, David Brown wrote:
>> On 01/02/17 07:48, Ian Collins wrote:
>
>>>>> Care to name and shame?
>
> The ones that gave warnings without any extra options were Pelles C,
> lccwin, and gcc. The other three that said nothing nothing were DMC,
> Tiny C and MSVC-2008.
>
>>> Even unadorned gcc complains...
>
> It doesn't complain very strongly. I couldn't see from the grammar of
> any C version that 'a=10;' was legal outside of a function.
>
>> It all depends on what Bart means by "compiles fine". Unadorned gcc
>> will happily compile:
>>
>> a = 10, b = 20, c = 30;
>>
>> int main(void) { }
>>
>> It /will/ give a warning "data definition has no type or storage class",
>> but it will compile the code just as though the missing "int" was there.
>> I can't find any way to turn off the warning, which is probably a good
>> thing.
>
> The problem is this, if you are trying to implement such a parser: do
> you deal with this strictly according to the grammar (and disallow it
> completely)? That sounds a good idea, but then it will reject code that
> will be passed by most other compilers with little problem.
>
It is fine to reject something that the grammar does not allow. It is
also fine to require code that is compatible with modern standards (C99
onwards). It is not unreasonable to consider accepting something
outside the grammar if it is in common use, supported by other tools,
and it would annoy your users if were /not/ supported by your tool.
However, I really can't see that applying in this case.
> However, the grammar also seems to allow these:
>
> const const const a; // no initial value
> int int int b;
>
> gcc allows the first (but 'implicit int'), and disallows the second
> (more than one type specifier).
>
> (It seems crazy to me that a grammar could be so sloppy and ambiguous,
> requiring masses of notes to clarify what is legal and what isn't. And I
> couldn't even find the notes pertaining to the int int int; I have to
> rely on trial and error using a well-regarded compiler (gcc).
>
> It's so easy to get right. Although C's untidy scheme where 'int' and
> 'long' are both independent type-specs, but 'long' can also be a
> modifier to 'int', doesn't help. And 'int static const unsigned const
> long const long volatile' is legal... What a language!)
>
Section 6.7.2 of N1570 (C11 draft) seems reasonably clear to me. "int
int" is not allowed - you can have /one/ list of type specifier from the
list given under "constraints".
On the other had, it is perfectly reasonable to allow more than one
"const" or other type qualifier in the same declaration - this allows
you to have "typedef const char cchar;" and then "const cchar c = 'a';".
Again, it is clear in the standards - section 6.7.3.
If you have been reading Annex A "(Informative) Language syntax summary"
and assuming that the BNF grammar covered all the details, you are bound
to make this sort of mistake. You have to read the actual standards to
see all the constraints - there is a reason why Annex A is labelled
"Informative".
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2017-02-01 13:22 +0000 |
| Message-ID | <o6snb9$v37$1@dont-email.me> |
| In reply to | #102904 |
On 01/02/2017 12:55, David Brown wrote: > On 01/02/17 12:39, BartC wrote: >> (It seems crazy to me that a grammar could be so sloppy and ambiguous, >> requiring masses of notes to clarify what is legal and what isn't. And I >> couldn't even find the notes pertaining to the int int int; I have to >> rely on trial and error using a well-regarded compiler (gcc). >> >> It's so easy to get right. Although C's untidy scheme where 'int' and >> 'long' are both independent type-specs, but 'long' can also be a >> modifier to 'int', doesn't help. And 'int static const unsigned const >> long const long volatile' is legal... What a language!) >> > > Section 6.7.2 of N1570 (C11 draft) seems reasonably clear to me. "int > int" is not allowed - you can have /one/ list of type specifier from the > list given under "constraints". Oh, OK, I didn't get that far! But it has to resort to listing all the combinations (but not the permutations) that are allowed. And which may be intermixed with other attributes. This is not very elegant (nor efficient) to parse and to check. (I notice you shouldn't use _Complex by itself, but have to combine it with float or double, which I hadn't realised. Yet usually you can. More laxity on the part of compilers.) > On the other had, it is perfectly reasonable to allow more than one > "const" or other type qualifier in the same declaration - this allows > you to have "typedef const char cchar;" and then "const cchar c = 'a';". > Again, it is clear in the standards - section 6.7.3. > > If you have been reading Annex A "(Informative) Language syntax summary" > and assuming that the BNF grammar covered all the details, you are bound > to make this sort of mistake. You have to read the actual standards to > see all the constraints - there is a reason why Annex A is labelled > "Informative". So the language /was/ informally thrown together (understandable in 1970), and only later were attempts made to properly define it. When it was presumably a little too late. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-01 16:30 +0100 |
| Message-ID | <o6suqv$q9r$1@dont-email.me> |
| In reply to | #102905 |
On 01/02/17 14:22, BartC wrote: > On 01/02/2017 12:55, David Brown wrote: >> On 01/02/17 12:39, BartC wrote: > > >>> (It seems crazy to me that a grammar could be so sloppy and ambiguous, >>> requiring masses of notes to clarify what is legal and what isn't. And I >>> couldn't even find the notes pertaining to the int int int; I have to >>> rely on trial and error using a well-regarded compiler (gcc). >>> >>> It's so easy to get right. Although C's untidy scheme where 'int' and >>> 'long' are both independent type-specs, but 'long' can also be a >>> modifier to 'int', doesn't help. And 'int static const unsigned const >>> long const long volatile' is legal... What a language!) >>> >> >> Section 6.7.2 of N1570 (C11 draft) seems reasonably clear to me. "int >> int" is not allowed - you can have /one/ list of type specifier from the >> list given under "constraints". > > Oh, OK, I didn't get that far! How can you be writing a parser, and complaining about what C does and does not allow, and how other compilers match the standards, when you haven't even bothered to /read/ the standards? How are you making making your code at the moment - by skim-reading a couple of Wikipedia articles then some trial-and-error runs with a few existing compilers? > But it has to resort to listing all the > combinations (but not the permutations) that are allowed. And which may > be intermixed with other attributes. This is not very elegant (nor > efficient) to parse and to check. The language has historical baggage. This is no surprise - its 40 years old and has gone through many revisions. Originally there was only "int" and "double", and other types had to be added in a way that allowed existing code to keep working. The result is a bit less consistent than if it had been designed with advice from time-travellers. You can do better when designing a /new/ language, but with C you have to live with what we have. > > (I notice you shouldn't use _Complex by itself, but have to combine it > with float or double, which I hadn't realised. Yet usually you can. More > laxity on the part of compilers.) It doesn't /matter/. Your parser does not need to accept "_Complex" on its own, because that would be an error. Or you can choose to accept it as meaning "_Complex double" like many other compilers. You are even free to interpret a plain "_Complex" as the same as "_Bool" if you like - it would still be conforming to the standards even if it would be rather unhelpful to users. > >> On the other had, it is perfectly reasonable to allow more than one >> "const" or other type qualifier in the same declaration - this allows >> you to have "typedef const char cchar;" and then "const cchar c = 'a';". >> Again, it is clear in the standards - section 6.7.3. >> >> If you have been reading Annex A "(Informative) Language syntax summary" >> and assuming that the BNF grammar covered all the details, you are bound >> to make this sort of mistake. You have to read the actual standards to >> see all the constraints - there is a reason why Annex A is labelled >> "Informative". > > So the language /was/ informally thrown together (understandable in > 1970), and only later were attempts made to properly define it. When it > was presumably a little too late. > Yes, the language was used for quite a while before there was a proper standard. And the language changed underway while it was in use. I know you like to put your fingers in your ears and sing "la, la, la" to a lot of what people try to tell you about C in this newsgroup, but surely it cannot be a surprise to you that C is a language with old roots? But that has nothing to do with the fact that the standards committee decided to specify the syntax of the language using a combination of BNF and some constraints, rather than making a significantly more complex BNF grammar. The constraints for type specifiers could, I believe, have been expressed in BNF - but doing so would make it harder to understand. If you are interested in making a C parser, read current C standards documents and learn the details. If you are interested in C history, read up about that.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-02-01 08:15 -0800 |
| Message-ID | <ln7f5999bi.fsf@kst-u.example.com> |
| In reply to | #102906 |
David Brown <david.brown@hesbynett.no> writes:
[...]
> But that has nothing to do with the fact that the standards committee
> decided to specify the syntax of the language using a combination of BNF
> and some constraints, rather than making a significantly more complex
> BNF grammar. The constraints for type specifiers could, I believe, have
> been expressed in BNF - but doing so would make it harder to understand.
Expressing those constraints in BNF would have been tedious and would
have made the grammar substantially larger. The type "unsigned long"
can also be written as "long unsigned", and there is code that depends
on that. Rather than permitting only the commonly used orders (whatever
they are), the standard allows any order.
A BNF grammar that permits `long unsigned int long` but forbids
`int unsigned int long` would be unwieldy, especially when other
keywords like const can legally be interspersed.
It probably would have been better to have a more restrictive grammar
from the beginning, but that wasn't practical.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-01 08:44 -0800 |
| Message-ID | <6d66a487-b263-403f-8d05-2474d41ae2b9@googlegroups.com> |
| In reply to | #102909 |
On Wednesday, February 1, 2017 at 10:14:01 AM UTC-6, Keith Thompson wrote: > It probably would have been better to have a more restrictive grammar > from the beginning, but that wasn't practical. Alternatively, it would have been better to recognize that some languages may be described much better in terms of parsing steps and states than as a BNF grammar. Every grammar which can be matched by a finite or push-down state machine will have an equivalent BNF grammar, but the BNF form may sometimes need to be far more complicated, and far less comprehensible, than the state machine upon which it is based. A state machine which accepts all inputs that don't contain the word "fnord", for example, would need six states, five of which have transitions only to the next state or back to start, and one of which has transitions only to itself. Visual inspection of the state machine would make its function easily apparent. An equivalent in BNF would be much more complicated, and even someone who knew that a BNF grammar was *supposed* to match any string that doesn't contain "fnord" would have to do a lot of work to determine whether it actually did so. Perhaps you can suggest a reason why a BNF description of the language would be more useful than the state-machine approach, because I really don't see one.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-02-01 20:56 +0100 |
| Message-ID | <o6teeo$ofn$1@dont-email.me> |
| In reply to | #102912 |
On 01/02/17 17:44, supercat@casperkitty.com wrote: > On Wednesday, February 1, 2017 at 10:14:01 AM UTC-6, Keith Thompson wrote: >> It probably would have been better to have a more restrictive grammar >> from the beginning, but that wasn't practical. > > Alternatively, it would have been better to recognize that some languages may > be described much better in terms of parsing steps and states than as a BNF > grammar. Every grammar which can be matched by a finite or push-down state > machine will have an equivalent BNF grammar, but the BNF form may sometimes > need to be far more complicated, and far less comprehensible, than the state > machine upon which it is based. > Alternatively, it would have been even better to recognize that some aspects of a language like C can be best described in BNF form, and other aspects can be best described in free text. Oh, wait - someone's thought of that already.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2017-02-01 08:29 -0800 |
| Message-ID | <910e144a-fbc1-43e6-a2d2-59aa44aebb72@googlegroups.com> |
| In reply to | #102906 |
On Wednesday, February 1, 2017 at 9:30:23 AM UTC-6, David Brown wrote: > How can you be writing a parser, and complaining about what C does and > does not allow, and how other compilers match the standards, when you > haven't even bothered to /read/ the standards? How are you making > making your code at the moment - by skim-reading a couple of Wikipedia > articles then some trial-and-error runs with a few existing compilers? The language Dennis Ritchie designed was not processed using a formal grammar, nor is a formal grammar the most efficient way to parse that language. In addition, I don't think a formal grammar works well as a human-readable way of describing it either. Since some compiler-generation tools are easiest to use when they have a formal grammar as a starting point, I think it is reasonable for the Standard to provide a grammar and say that implementations are required to handle the cases described by the Standard and are not required to handle cases outside the grammar. Given the charter of the Committee, however, I really doubt that the Committee intended that compilers should be required to reject forms that they had accepted previously and which may be in use by production code.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web