Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

what does this warning mean ?

14 views
Skip to first unread message

Heinrich Pumpernickel

unread,
Sep 26, 2007, 10:24:50 PM9/26/07
to
what does this warning mean ?


#include <stdio.h>

int main()
{
long l = 100;

printf("l is %li\n", l * 10L);

return 0;
}


when i compile this program with lcc-win32 it prints

lcc -A -ansic -O long.c -o long.obj
Warning c:\tmp\long.c: 4 old-style function definition for 'main'
Warning c:\tmp\long.c: 4 missing prototype for 'main'
Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
Expected long int got int
0 errors, 4 warnings


warning 1-3: how to give prototype for main ?

warning 4: i gave it long int but it says it got int . even
'(long)l * 10L' gives same warning . how to cast this properly ?
is it safe to ignore ???

gcc prints no warnings .

--
mfg, heinrich :)

Richard Heathfield

unread,
Sep 26, 2007, 10:47:17 PM9/26/07
to
Heinrich Pumpernickel said:

> what does this warning mean ?
>
>
> #include <stdio.h>
>
> int main()
> {
> long l = 100;
>
> printf("l is %li\n", l * 10L);
>
> return 0;
> }
>
>
> when i compile this program with lcc-win32 it prints
>
> lcc -A -ansic -O long.c -o long.obj
> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> Expected long int got int
> 0 errors, 4 warnings
>
>
> warning 1-3: how to give prototype for main ?

change int main() to int main(void)

>
> warning 4: i gave it long int but it says it got int . even
> '(long)l * 10L' gives same warning .

Implementations are given licence to produce diagnostic messages for any
reason they like. Mostly, implementors are very good at not giving out
spurious messages, but sometimes the occasional duff message is displayed.
This is one such case.

The "usual arithmetic conversions" require that "if either operand has type
long int, the other operand is converted to long int", which is doubly
true here, so we definitely have long * long, which definitely results in
a long because "The purpose is to yield a common type, which is also the
type of the result" (both citations are from 3.2.1.5 of C89).

So the code is right. The implementation's production of a diagnostic
message is not non-conforming (because implementations are allowed to
produce any old rubbish in the diagnostics as long as correct code works
correctly - and I presume it does?), but it does demonstrate low QoI, and
it makes you wonder how many other spurious diagnostics your
implementation is producing.

> how to cast this properly ?

Please don't. There's no point. The value already has the proper type.
Casting is not going to help.

> is it safe to ignore ???

The code is legal C. Is it safe to use an implementation that gives
misleading diagnostics for legal C? That's a judgement call that nobody
else (apart from perhaps your boss) can make for you.

> gcc prints no warnings .

Ah, there's a Great Big Hint for you if ever I saw one.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Keith Thompson

unread,
Sep 26, 2007, 11:01:40 PM9/26/07
to
Heinrich Pumpernickel <lan...@linuxmail.org> writes:
> what does this warning mean ?
>
>
> #include <stdio.h>
>
> int main()
> {
> long l = 100;
>
> printf("l is %li\n", l * 10L);
>
> return 0;
> }
>
>
> when i compile this program with lcc-win32 it prints
>
> lcc -A -ansic -O long.c -o long.obj
> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> Expected long int got int
> 0 errors, 4 warnings
>
>
> warning 1-3: how to give prototype for main ?

Use 'int main(void)' rather than 'int main()'.

> warning 4: i gave it long int but it says it got int . even
> '(long)l * 10L' gives same warning . how to cast this properly ?
> is it safe to ignore ???
>
> gcc prints no warnings .

I don't know. Did you copy-and-paste the exact code and error
messages? If not, check for transcription errors, such as digit 1'
vs. letter 'l'.

It could be a bug in lcc-win32. Post the details to
comp.compilers.lcc, or use whatever support channels are available.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Richard Heathfield

unread,
Sep 26, 2007, 11:06:56 PM9/26/07
to
Keith Thompson said:

> Heinrich Pumpernickel <lan...@linuxmail.org> writes:

<snip>

>> warning 4: i gave it long int but it says it got int . even
>> '(long)l * 10L' gives same warning . how to cast this properly ?
>> is it safe to ignore ???

<snip>



> It could be a bug in lcc-win32.

Nothing he has said suggests anything of the sort. It is strictly a QoI
matter. A bug-free conforming implementation could legally produce that
diagnostic message, despite correct code and correct runtime behaviour.

Eric Sosman

unread,
Sep 26, 2007, 11:08:48 PM9/26/07
to
Heinrich Pumpernickel wrote:
> what does this warning mean ?
>
>
> #include <stdio.h>
>
> int main()
> {
> long l = 100;
>
> printf("l is %li\n", l * 10L);
>
> return 0;
> }
>
>
> when i compile this program with lcc-win32 it prints
>
> lcc -A -ansic -O long.c -o long.obj
> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> Expected long int got int
> 0 errors, 4 warnings

Keep in mind that a compiler is free to issue as many
diagnostic messages as it likes, about any matters it wants
to, even in situations where the Standard does not require
a diagnostic. If it wants to complain about the way you
indent your code or about your choice of variable names or
about being forced to compile code after quitting time on
Friday, it can do so. It can't reject the program for such
a reason, but it can issue diagnostics anyhow.

Because of this, the goal of "Code so clean it gets no
warnings from any compiler" is not always achievable.

> warning 1-3: how to give prototype for main ?

Modern style recommends `int main(void)', but there is
nothing actually wrong with the code as written. In particular,
your definition of main() conforms to the original 1989 ANSI
C Standard and all its successors, despite what the "non-ANSI"
warning says.

> warning 4: i gave it long int but it says it got int . even
> '(long)l * 10L' gives same warning . how to cast this properly ?
> is it safe to ignore ???

The code is correct. I don't know why the compiler says
it isn't.

> gcc prints no warnings .

Plain "gcc" lets quite a lot of looseness get by. But
even if you crank it up to "gcc -Wall -W -ansi -pedantic"
I don't think it will issue warnings for your code.

Some compilers can translate several different (but usually
related) languages if invoked or configured for them. Are you
sure your compiler is configured to recognize C, and not some
related language like C++ or Objective-C?

--
Eric Sosman
eso...@ieee-dot-org.invalid

Heinrich Pumpernickel

unread,
Sep 27, 2007, 12:42:02 AM9/27/07
to

somebody suggested

printf("l is %li\n", (long)(l * 10L));

and now this warning disappeared . can l * 10L ever be int ?
(my boss says thats illegal)

>> is it safe to ignore ???
>
>The code is legal C. Is it safe to use an implementation that gives
>misleading diagnostics for legal C? That's a judgement call that nobody
>else (apart from perhaps your boss) can make for you.
>
>> gcc prints no warnings .
>
>Ah, there's a Great Big Hint for you if ever I saw one.

--
mfg, heinrich :)

pete

unread,
Sep 27, 2007, 12:58:13 AM9/27/07
to
Heinrich Pumpernickel wrote:
>
> On Thu, 27 Sep 2007 02:47:17 +0000, Richard Heathfield
> <r...@see.sig.invalid> wrote:
>
> >Heinrich Pumpernickel said:
> >
> >> what does this warning mean ?
> >>
> >>
> >> #include <stdio.h>
> >>
> >> int main()
> >> {
> >> long l = 100;
> >>
> >> printf("l is %li\n", l * 10L);
> >>
> >> return 0;
> >> }

> somebody suggested


>
> printf("l is %li\n", (long)(l * 10L));
>
> and now this warning disappeared . can l * 10L ever be int ?

No.
Even just (l * 10) is still type long int.

--
pete

Richard Heathfield

unread,
Sep 27, 2007, 1:08:36 AM9/27/07
to
Heinrich Pumpernickel said:

<snip>


>
> somebody suggested
>
> printf("l is %li\n", (long)(l * 10L));
>
> and now this warning disappeared .

The cast is unnecessary and bad style. When you multiply a long int by a
long int, the result is a long int. The cast is an attempt to convert a
long int into a long int - a NOP if ever there was one!

You have four reasonable courses of action:

1: use the cast to suppress the warning - this is the worst option, because
you're muddying the code to cater to a compiler's whim. This damages
readability and maintainability; it is likely to confuse people.

2: put up with the warning - this is better than Option 1, but everyone
likes a clean compile if they can get one.

3: get the implementor to change the implementation so that it doesn't
issue this spurious diagnostic message - how good an option this is will
depend on the implementor; some implementors do not respond well to
criticism. By the way, you can't claim that it's a bug, because the
observable behaviour of the compiler does appear to be conforming in this
case. It's a quality of implementation (QoI) issue, not a conformance
issue.

4: use a better compiler - this is the option I would recommend in this
case, although Option 3 is certainly worth a try.

> can l * 10L ever be int ?

No, never. 10L is a long int. Assuming that the multiplication is legal, we
have the following possibilities:

Type of l Conversion
long double 10L is converted to long double; l * 10L is long double
double 10L is converted to double; l * 10L is double
float 10L is converted to float; l * 10L is float
unsigned long 10L is converted to unsigned long; l * 10L is unsigned long
long No conversions are necessary; l * 10L is long int
unsigned int if LONG_MAX >= UINT_MAX, l is converted to long int, and
l * 10L is long int; otherwise, both operands are converted
to unsigned long int, and l * 10L is unsigned long int
int, short int,\
unsigned short, \
unsigned char, : l is promoted to long int, and l * 10L is long int
signed char, /
char /


> (my boss says thats illegal)

He's right. In none of the above cases does the result of the expression
have type int, and an implementation that produces an int from a
multiplication involving a long int is not a conforming implementation.

<snip>

Old Wolf

unread,
Sep 27, 2007, 1:37:21 AM9/27/07
to
On Sep 27, 3:06 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> Nothing he has said suggests anything of the sort. It is strictly a QoI
> matter. A bug-free conforming implementation could legally produce that
> diagnostic message, despite correct code and correct runtime behaviour.

I would still consider it a bug. It is possible for
a compiler to conform to the C standard, yet still
have bugs.

Richard Heathfield

unread,
Sep 27, 2007, 1:48:33 AM9/27/07
to
Old Wolf said:

> On Sep 27, 3:06 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> Nothing he has said suggests anything of the sort. It is strictly a QoI
>> matter. A bug-free conforming implementation could legally produce that
>> diagnostic message, despite correct code and correct runtime behaviour.
>
> I would still consider it a bug.

If it were my implementation, I'd agree.

> It is possible for a compiler to conform to the C standard, yet still
> have bugs.

Indeed. Nevertheless, whether a particular (conforming) behaviour
constitutes a bug depends on whether the behaviour is intentional, and who
can know that, apart from the person or people who specified the behaviour
in the first place? If the implementation's spec says "if they try to
multiply a long int by a long int in a printf argument expression and then
print it with %li, Do The Right Thing in terms of output, but produce a
silly, confusing, and preferably misleading warning just to mess with
their heads" and if that spec accurately reflects the intent of the
specifier, then it's not a bug in the implementation.

Martin Ambuhl

unread,
Sep 27, 2007, 1:52:41 AM9/27/07
to
Heinrich Pumpernickel wrote:
> what does this warning mean ?
>
>
> #include <stdio.h>
>
> int main()
> {
> long l = 100;
>
> printf("l is %li\n", l * 10L);
>
> return 0;
> }
>
>
> when i compile this program with lcc-win32 it prints
>
> lcc -A -ansic -O long.c -o long.obj
> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
This warning is bogus and incorrect.

> Warning c:\tmp\long.c: 4 missing prototype for 'main'

This warning is bogus and incorrect.

> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition

This warning is bogus and incorrect.

> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> Expected long int got int

This warning is bogus and incorrect.

> 0 errors, 4 warnings
> warning 1-3: how to give prototype for main ?
>
> warning 4: i gave it long int but it says it got int . even
> '(long)l * 10L' gives same warning . how to cast this properly ?
> is it safe to ignore ???

Complain to Jacob. His compiler is broken.

Keith Thompson

unread,
Sep 27, 2007, 2:18:48 AM9/27/07
to
Richard Heathfield <r...@see.sig.invalid> writes:
> Keith Thompson said:
>> Heinrich Pumpernickel <lan...@linuxmail.org> writes:
>
> <snip>
>
>>> warning 4: i gave it long int but it says it got int . even
>>> '(long)l * 10L' gives same warning . how to cast this properly ?
>>> is it safe to ignore ???
>
> <snip>
>
>> It could be a bug in lcc-win32.
>
> Nothing he has said suggests anything of the sort. It is strictly a QoI
> matter. A bug-free conforming implementation could legally produce that
> diagnostic message, despite correct code and correct runtime behaviour.

Perhaps we're using the word "bug" differently. There's no indication
that the compiler violates the standard. Nevertheless, if it produces
a diagnostic message claiming that the program passed an int to
printf, when in fact it passed a long, I call that a bug.

I suppose one could argue that only a violation of the standard should
be considered a "bug". But I note that the standard doesn't define,
or even use, that word, so I feel free to use it in what I think is a
reasonable manner.

Richard Heathfield

unread,
Sep 27, 2007, 3:17:32 AM9/27/07
to
Keith Thompson said:
> Richard Heathfield <r...@see.sig.invalid> writes:

<snip>

>> A bug-free conforming implementation could legally produce that
>> diagnostic message, despite correct code and correct runtime behaviour.
>
> Perhaps we're using the word "bug" differently.

Perhaps. I've dealt with this matter elsethread. (Maybe you've read it by
now, so I won't bang on about it again.)

jacob navia

unread,
Sep 27, 2007, 3:22:07 AM9/27/07
to

Hi Heinrich!

1) Lcc-win does NOT print ANY warning at the standard warning level.
You invoked the option -A, that increases the warning level, and
produces in a few cases wrong warnings.
2) If you increase the warning level to its MAXIMUM, those warnings
are printed.
3) Note that int main() defines a function that will take an
unspecified number of arguments. It does NOT mean that it is
a void function. C is NOT C++. The first warning is justified
4) int main() is NOT a function prototype. Second warning is
justified.
5) The correct prototype is int main(void). Third warning is
justified. The ANSI C Norm specifies explicitely that.
6) The next warning is unjustified. The compiler has transformed
the type 'long' in type int internally, since in this particular
implementation sizeof(long) == sizeof(int). I will supress this
warning in the next version. The compiler will NOT warn
when you write "%li" and you give it an int either, but that
is a smaller problem.

Many people will tell you here that gcc is a better compiler
than lcc-win. This is true for a number of features. Lcc-win is
a small compiler that can't compete with either MSVC or gcc.


jacob

jacob navia

unread,
Sep 27, 2007, 3:31:10 AM9/27/07
to
Heinrich Pumpernickel wrote:
[snip]

> gcc prints no warnings .


gcc misses a warning for an incorrect definition
of the 'main' function then.

jacob navia

unread,
Sep 27, 2007, 3:36:13 AM9/27/07
to
Martin Ambuhl wrote:
> Heinrich Pumpernickel wrote:
>> what does this warning mean ?
>>
>>
>> #include <stdio.h>
>>
>> int main()
>> {
>> long l = 100;
>>
>> printf("l is %li\n", l * 10L);
>>
>> return 0;
>> }
>>
>>
>> when i compile this program with lcc-win32 it prints
>>
>> lcc -A -ansic -O long.c -o long.obj
>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> This warning is bogus and incorrect.
>

Hi Ambuhl
You mean then that

int fn();

is the same as
int fn(void);

???

Note that

int fn() means a function with an UNSPECIFIED number of parameters!

>> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> This warning is bogus and incorrect.
>

You mean then that

int fn() is a correct prototype?

This is completely WRONG.

>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> This warning is bogus and incorrect.
>

The definition of main is int main(void) or int main(int,char **)
not int main()

>> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
>> Expected long int got int
> This warning is bogus and incorrect.
>

There. You have at least one hit!

Congratulations Mr Ambuhl. 1 out of 4 is quite a good progress for you.
Next time you will achive 2 wrongs for 2 correct. Keep on.

Keith Thompson

unread,
Sep 27, 2007, 3:40:38 AM9/27/07
to
Martin Ambuhl <mam...@earthlink.net> writes:
> Heinrich Pumpernickel wrote:
>> what does this warning mean ?
>> #include <stdio.h>
>> int main()
>> {
>> long l = 100;
>> printf("l is %li\n", l * 10L);
>> return 0;
>> }
>> when i compile this program with lcc-win32 it prints
>> lcc -A -ansic -O long.c -o long.obj
>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> This warning is bogus and incorrect.
>
>> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> This warning is bogus and incorrect.
>
>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> This warning is bogus and incorrect.

Well, partly. It certainly isn't "non-ANSI" (though why the messages
refer to ANSI rather than ISO is a mystery). But 'int main()' rather
than 'int main(void)' is an old-style declaration, and C99 6.11.6
says:

The use of function declarators with empty parentheses (not
prototype-format parameter type declarators) is an obsolescent
feature.

>> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
>> Expected long int got int
> This warning is bogus and incorrect.

Agreed.

[...]

> Complain to Jacob. His compiler is broken.

Well, it has a bug.

Philip Potter

unread,
Sep 27, 2007, 4:10:13 AM9/27/07
to

What's incorrect about the main() definition?

You're correct that the only valid prototypes are int main(void) or int
main(int, char**). A prototype is not /required/ to be provided, however.

int main() is ugly and obsolescent. But it is not (yet) incorrect.

--
Philip Potter pgp <at> doc.ic.ac.uk

Keith Thompson

unread,
Sep 27, 2007, 4:10:44 AM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> writes:
[...]

> 3) Note that int main() defines a function that will take an
> unspecified number of arguments. It does NOT mean that it is
> a void function. C is NOT C++. The first warning is justified

In a function declaration that's not a definition, empty parentheses
indicate that the function takes an unspecified number and type of
arguments. But in a function *definition*, empty parentheses imply
that the function has no parameters.

> 4) int main() is NOT a function prototype. Second warning is
> justified.
> 5) The correct prototype is int main(void). Third warning is
> justified. The ANSI C Norm specifies explicitely that.

Just out of curiosity, why do you refer to ANSI C rather than ISO C?
The current C standard, C99, was issued by ISO; ANSI merely adopted
it.

There's a convoluted argument (I don't recall the details) that
'int main() { ... }' is invalid, but the general consensus is that
it's perfectly valid (though obsolescent).

[...]

Flash Gordon

unread,
Sep 27, 2007, 3:09:13 AM9/27/07
to
Martin Ambuhl wrote, On 27/09/07 06:52:

> Heinrich Pumpernickel wrote:
>> what does this warning mean ?
>>
>>
>> #include <stdio.h>
>>
>> int main()

<snip>

>> when i compile this program with lcc-win32 it prints
>>
>> lcc -A -ansic -O long.c -o long.obj
>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> This warning is bogus and incorrect.

It may be bogus, but it is in fact (almost) correct. Not specifying void
for an empty parameter list makes it an old-style declaration rather
than a prototype. It is, of course, also a definition as well as a
declaration.

I agree completely with the rest of your points.

<snip>

>> warning 4: i gave it long int but it says it got int . even
>> '(long)l * 10L' gives same warning . how to cast this properly ?
>> is it safe to ignore ???
>
> Complain to Jacob. His compiler is broken.

Either that or the code posted here is not the code that was compiled.
--
Flash Gordon

Richard Heathfield

unread,
Sep 27, 2007, 4:07:23 AM9/27/07
to
Keith Thompson said:

> Martin Ambuhl <mam...@earthlink.net> writes:
<snip>


>>
>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>> This warning is bogus and incorrect.
>
> Well, partly. It certainly isn't "non-ANSI" (though why the messages
> refer to ANSI rather than ISO is a mystery). But 'int main()' rather
> than 'int main(void)' is an old-style declaration, and C99 6.11.6
> says:
>
> The use of function declarators with empty parentheses (not
> prototype-format parameter type declarators) is an obsolescent
> feature.

Indeed. Nevertheless, it remains a feature.

Richard Heathfield

unread,
Sep 27, 2007, 4:10:31 AM9/27/07
to
Martin Ambuhl said:

> Heinrich Pumpernickel wrote:
>> what does this warning mean ?
>>
>>
>> #include <stdio.h>
>>
>> int main()
>> {
>> long l = 100;
>>
>> printf("l is %li\n", l * 10L);
>>
>> return 0;
>> }
>>
>>
>> when i compile this program with lcc-win32 it prints
>>
>> lcc -A -ansic -O long.c -o long.obj
>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> This warning is bogus and incorrect.

It's bogus, but not incorrect: int main() is indeed an old-style function
definition, and in any case any implementation can issue any diagnostics
it likes.

>> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> This warning is bogus and incorrect.

It's bogus, but not incorrect: int main() is not a prototype, so the
prototype for main (which is not required) is indeed missing, and in any
case any implementation can issue any diagnostics it likes. In this case,
it's a bit like saying "you didn't #include <signal.h>" - i.e. true but,
for the given code, silly.

>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> This warning is bogus and incorrect.

Agreed.

>> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
>> Expected long int got int
> This warning is bogus and incorrect.

Agreed.

> Complain to Jacob. His compiler is broken.

Agreed.

Francin...@googlemail.com

unread,
Sep 27, 2007, 4:27:55 AM9/27/07
to
On Sep 27, 8:36 am, jacob navia <ja...@jacob.remcomp.fr> wrote:
> Martin Ambuhl wrote:
> > Heinrich Pumpernickel wrote:
> >> what does this warning mean ?
>
> >> #include <stdio.h>
>
> >> int main()
> >> {
> >> long l = 100;
>
> >> printf("l is %li\n", l * 10L);
>
> >> return 0;
> >> }
>
> >> when i compile this program with lcc-win32 it prints
>
> >> lcc -A -ansic -O long.c -o long.obj
> >> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> > This warning is bogus and incorrect.
>
> Hi Ambuhl
> You mean then that
>
> int fn();
>
> is the same as
> int fn(void);
>
> ???
>
> Note that
>
> int fn() means a function with an UNSPECIFIED number of parameters!

But that wasn't what was in the original code. The original code went:

int main()
{
...
}

In a function DEFINITION like this, () is completely equivalent to
(void) (I remember looking it up once...)

You're right that in a DECLARATION, they are different:

int main(); /* main takes an unspecified number of parameters */
int main(void); /* main takes no parameters */

So the warning is indeed bogus and incorrect. :)

>
> >> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> > This warning is bogus and incorrect.
>
> You mean then that
>
> int fn() is a correct prototype?
>
> This is completely WRONG.

But a definition serves as a prototype. I'd expect this warning to
mean I'd called a function with no prototype in scope, which isn't the
case here.

>
> >> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> > This warning is bogus and incorrect.
>
> The definition of main is int main(void) or int main(int,char **)
> not int main()

Exactly as above... in a DEFINITION, int main() is absolutely fine.
(As in just main() in C90.)

>
> >> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> >> Expected long int got int
> > This warning is bogus and incorrect.
>
> There. You have at least one hit!
>
> Congratulations Mr Ambuhl. 1 out of 4 is quite a good progress for you.
> Next time you will achive 2 wrongs for 2 correct. Keep on.

4 out of 4 and a gold sticker, I'd have said. :)

jacob navia

unread,
Sep 27, 2007, 4:49:18 AM9/27/07
to
Francin...@googlemail.com wrote:
>
> But that wasn't what was in the original code. The original code went:
>
> int main()
> {
> ...
> }
>
> In a function DEFINITION like this, () is completely equivalent to
> (void) (I remember looking it up once...)
>

This is the definition of a function with an unspecified
number of arguments.

> You're right that in a DECLARATION, they are different:


>
> int main(); /* main takes an unspecified number of parameters */
> int main(void); /* main takes no parameters */
>
> So the warning is indeed bogus and incorrect. :)
>

I do not think so. But I am not a language lawyer.


> But a definition serves as a prototype. I'd expect this warning to
> mean I'd called a function with no prototype in scope, which isn't the
> case here.
>

This means that main has no prototype since you did NOT
provide a prototype and main *IS* always called!

>>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>>> This warning is bogus and incorrect.
>> The definition of main is int main(void) or int main(int,char **)
>> not int main()
>
> Exactly as above... in a DEFINITION, int main() is absolutely fine.
> (As in just main() in C90.)
>

It is absolutely fine. It is just an obsolescent feature, and
if you do take the HIGHEST warning level you get that warning!

Do not like it?

Then call the compiler with no special warning level and you see no
warnings. Under the HIGHEST warning level I will warn about obsolescent
features. What's wrong with that?

jacob navia

unread,
Sep 27, 2007, 4:53:42 AM9/27/07
to

Under the highest warning level, a compiler should warn
about

int main()

since it is an obsolete syntax. Note that lcc-win does NOT
warn in the default warning level.

Richard Bos

unread,
Sep 27, 2007, 5:08:40 AM9/27/07
to
Keith Thompson <ks...@mib.org> wrote:

> jacob navia <ja...@jacob.remcomp.fr> writes:
> [...]

> > 5) The correct prototype is int main(void). Third warning is
> > justified. The ANSI C Norm specifies explicitely that.
>
> Just out of curiosity, why do you refer to ANSI C rather than ISO C?
> The current C standard, C99, was issued by ISO; ANSI merely adopted
> it.

Even for the former Standard, jacob should refer to the ISO Standard.
ANSI should not be relevant to him, because he's a Frog.

Richard

Martin Ambuhl

unread,
Sep 27, 2007, 5:07:00 AM9/27/07
to
jacob navia wrote:
> Martin Ambuhl wrote:
>> Heinrich Pumpernickel wrote:
>>> what does this warning mean ?
>>>
>>>
>>> #include <stdio.h>
>>>
>>> int main()
>>> {
>>> long l = 100;
>>>
>>> printf("l is %li\n", l * 10L);
>>>
>>> return 0;
>>> }
>>>
>>>
>>> when i compile this program with lcc-win32 it prints
>>>
>>> lcc -A -ansic -O long.c -o long.obj
>>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
>> This warning is bogus and incorrect.
>>
>
> Hi Ambuhl
> You mean then that
>
> int fn();
>
> is the same as
> int fn(void);
>
> ???

No. Nowhere did I say that. Why would you even suggest that I "meant"
something that I did not in anyway address.
There is nothing to warn about.
There is nothing "old-style" about it.
The diagnostic is an editorial statement of personal preference on the
part of the compiler writer and suggests a problem where there is none.
The warning is bogus. It is wrong. While Jacob's compiler is free to
emit what ever bogus diagnostics it wants to, that it does so makes it
broken as far as any serious user is concerned.

>
> Note that
>
> int fn() means a function with an UNSPECIFIED number of parameters!
>
>>> Warning c:\tmp\long.c: 4 missing prototype for 'main'
>> This warning is bogus and incorrect.
>>
>
> You mean then that
>
> int fn() is a correct prototype?
>
> This is completely WRONG.
>
>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>> This warning is bogus and incorrect.
>>
>
> The definition of main is int main(void) or int main(int,char **)
> not int main()
>
>>> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
>>> Expected long int got int
>> This warning is bogus and incorrect.
>>
>
> There. You have at least one hit!
>
> Congratulations Mr Ambuhl. 1 out of 4 is quite a good progress for you.
> Next time you will achive 2 wrongs for 2 correct. Keep on.

As usual, Jacob, you are full of it. If you continue to prove that you
are completely ignorant, you may convince us not to bother with
lcc-win32 as well.

>

jacob navia

unread,
Sep 27, 2007, 5:07:36 AM9/27/07
to Richard Bos

You are a typical slave of HMQ (her majesty the queen).

I am not a frog. I live in a country where some people
eat parts of frogs. "Nuance" :-)

Martin Ambuhl

unread,
Sep 27, 2007, 5:10:09 AM9/27/07
to

Ignore Jacob. He hasn't a clue.

Keith Thompson

unread,
Sep 27, 2007, 6:35:14 AM9/27/07
to

That kind of epithet is uncalled for.

Francin...@googlemail.com

unread,
Sep 27, 2007, 7:25:31 AM9/27/07
to
On Sep 27, 9:49 am, jacob navia <ja...@jacob.remcomp.fr> wrote:

> Francine.Ne...@googlemail.com wrote:
>
> > But that wasn't what was in the original code. The original code went:
>
> > int main()
> > {
> > ...
> > }
>
> > In a function DEFINITION like this, () is completely equivalent to
> > (void) (I remember looking it up once...)
>
> This is the definition of a function with an unspecified
> number of arguments.
>
> > You're right that in a DECLARATION, they are different:
>
> > int main(); /* main takes an unspecified number of parameters */
> > int main(void); /* main takes no parameters */
>
> > So the warning is indeed bogus and incorrect. :)
>
> I do not think so. But I am not a language lawyer.

Do you think it might be a good idea to become a language lawyer if
you're maintaining a compiler? :)

I looked it up again:

(6.5.4.3) An empty list in a function declarator that is part of a
function definition specifies that the function has no parameters. The
empty list in a function declarator that is not part of a function
definition specifies that no information about the number or types of
the parameters is supplied.

>
> > But a definition serves as a prototype. I'd expect this warning to
> > mean I'd called a function with no prototype in scope, which isn't the
> > case here.
>
> This means that main has no prototype since you did NOT
> provide a prototype and main *IS* always called!

(6.7.1) If the declarator includes a parameter type list... such a
declarator also serves as a function prototype for later calls to the
same function in the same translation unit.

Now you need to observe that the empty list is a list...

>
> >>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> >>> This warning is bogus and incorrect.
> >> The definition of main is int main(void) or int main(int,char **)
> >> not int main()
>
> > Exactly as above... in a DEFINITION, int main() is absolutely fine.
> > (As in just main() in C90.)
>
> It is absolutely fine. It is just an obsolescent feature, and
> if you do take the HIGHEST warning level you get that warning!
>
> Do not like it?
>
> Then call the compiler with no special warning level and you see no
> warnings. Under the HIGHEST warning level I will warn about obsolescent
> features. What's wrong with that?

Nothing wrong with that, but why not say "int main() is obsolescent
syntax" (which has the benefit of being true), rather than "int
main()' is a non-ANSI definition" (which has the drawback of being
false)?

(Note well that obsolescent != obsolete.)

Richard Bos

unread,
Sep 27, 2007, 7:40:57 AM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> wrote:

> Richard Bos wrote:
> > Keith Thompson <ks...@mib.org> wrote:
> >
> >> jacob navia <ja...@jacob.remcomp.fr> writes:
> >> [...]
> >>> 5) The correct prototype is int main(void). Third warning is
> >>> justified. The ANSI C Norm specifies explicitely that.
> >> Just out of curiosity, why do you refer to ANSI C rather than ISO C?
> >> The current C standard, C99, was issued by ISO; ANSI merely adopted
> >> it.
> >
> > Even for the former Standard, jacob should refer to the ISO Standard.
> > ANSI should not be relevant to him, because he's a Frog.
>

> You are a typical slave of HMQ (her majesty the queen).

And you are illiterate, where headers are concerned. I'm a subject of
Hare Majesteit de Koningin, not of Her Majesty the Queen.

(My point would have stood as strongly if _you_ had been a subject of
either: we're all in Europe, not in the USA. ANSI is irrelevant to both
of us.)

Richard

Richard Heathfield

unread,
Sep 27, 2007, 7:48:17 AM9/27/07
to
Richard Bos said:

> jacob navia <ja...@jacob.remcomp.fr> wrote:
>
>> Richard Bos wrote:

<snip>


>> >
>> > Even for the former Standard, jacob should refer to the ISO Standard.
>> > ANSI should not be relevant to him, because he's a Frog.
>>
>> You are a typical slave of HMQ (her majesty the queen).
>
> And you are illiterate, where headers are concerned.

Indeed he is.

> I'm a subject of
> Hare Majesteit de Koningin, not of Her Majesty the Queen.

Indeed you are.

>
> (My point would have stood as strongly if _you_ had been a subject of
> either: we're all in Europe,

Speak for yourself! :-)

> not in the USA. ANSI is irrelevant to both of us.)

Technically you're correct, but I don't think it's really such a big deal.
ANSI were the first national standards body to produce a C standard, and
the first conforming compilers all claimed ANSI conformance, not ISO
conformance. K&R2 has "ANSI C" plastered over the cover. It's hardly
surprising if people refer to standard C as "ANSI C". I'd rather save
pickiness for where it matters - such as, for example, not classifying the
UK as part of Europe. The English Channel is there for a reason. :-)

Joachim Schmitz

unread,
Sep 27, 2007, 7:51:15 AM9/27/07
to
"Richard Heathfield" <r...@see.sig.invalid> schrieb im Newsbeitrag
news:_bSdnbKKqKpsCmbb...@bt.com...

> I'd rather save
> pickiness for where it matters - such as, for example, not classifying the
> UK as part of Europe. The English Channel is there for a reason. :-)
You mean the Frensh Channel?

And believe it or nor, the UK is part of Europe, it is not a continent of
it's own and is even a member in the EU (still)

Bye, Jojo


Joachim Schmitz

unread,
Sep 27, 2007, 7:52:29 AM9/27/07
to

"Joachim Schmitz" <nospa...@schmitz-digital.de> schrieb im Newsbeitrag
news:fdg5g4$kd4$1...@online.de...
s/in/of/g

Bye, Jojo


Richard Heathfield

unread,
Sep 27, 2007, 7:57:58 AM9/27/07
to
Joachim Schmitz said:

> "Richard Heathfield" <r...@see.sig.invalid> schrieb im Newsbeitrag
> news:_bSdnbKKqKpsCmbb...@bt.com...
>> I'd rather save
>> pickiness for where it matters - such as, for example, not classifying
>> the UK as part of Europe. The English Channel is there for a reason. :-)
> You mean the Frensh Channel?

Nope. I can read a map, same as anyone, and on my map of the universe it is
clearly marked as the English Channel. I don't object to calling it the
South Sea, though, if you'd prefer to do that.

>
> And believe it or nor, the UK is part of Europe, it is not a continent of
> it's own and is even a member in the EU (still)

I'm glad you think so. Just so long as Europe stays on its side of the
water, you can think what you like. :-)

Richard

unread,
Sep 27, 2007, 8:04:26 AM9/27/07
to
Richard Heathfield <r...@see.sig.invalid> writes:

> Richard Bos said:
>
>> jacob navia <ja...@jacob.remcomp.fr> wrote:
>>
>>> Richard Bos wrote:
> <snip>
>>> >
>>> > Even for the former Standard, jacob should refer to the ISO Standard.
>>> > ANSI should not be relevant to him, because he's a Frog.
>>>
>>> You are a typical slave of HMQ (her majesty the queen).
>>
>> And you are illiterate, where headers are concerned.
>
> Indeed he is.

"Indeed", you can't resist can you? If you are going to killfile Jacob
then have the strength of character not to bitch and whine about him on
other peoples replies. You are responsible for more OT preening and
strutting than all the rest that you complain so audibly about when
things don't go your way. Maybe it is time for the killfile to be dusted
off.


Army1987

unread,
Sep 27, 2007, 8:21:32 AM9/27/07
to
On Thu, 27 Sep 2007 08:07:23 +0000, Richard Heathfield wrote:

> Keith Thompson said:
[unsnip]


>> Martin Ambuhl <mam...@earthlink.net> writes:
>>> Heinrich Pumpernickel wrote:
>>>> what does this warning mean ?
>>>> #include <stdio.h>
>>>> int main()
>>>> {
>>>> long l = 100;
>>>> printf("l is %li\n", l * 10L);
>>>> return 0;
>>>> }
>>>> when i compile this program with lcc-win32 it prints
>>>> lcc -A -ansic -O long.c -o long.obj
>>>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'

>>> This warning is bogus and incorrect.
>>>

>>>> Warning c:\tmp\long.c: 4 missing prototype for 'main'


>>> This warning is bogus and incorrect.
>>>>
>>>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>>>> This warning is bogus and incorrect.
>>>
>> Well, partly. It certainly isn't "non-ANSI" (though why the messages
>> refer to ANSI rather than ISO is a mystery). But 'int main()' rather
>> than 'int main(void)' is an old-style declaration, and C99 6.11.6
>> says:
>>
>> The use of function declarators with empty parentheses (not
>> prototype-format parameter type declarators) is an obsolescent
>> feature.
>
> Indeed. Nevertheless, it remains a feature.

Well, it doesn't make the third of those warnings correct, but it
does cause the first or the second of them non-bogus. I don't
think it is bogus to issue a warning for the use of obsolescent
features. (But issuing *both* warnings *is* bogus, as they say
almost exactly the same thing; and if the warning read "function
declarations with empty parentheses are an obsolescent feature" it
would be more useful.)
Anyway, the warning "printf argument mismatch for format i.
Expected long int got int" is totally wrong. It doesn't make lcc
broken by itself (the standard allows an implementation to issue
whatever diagnostics it likes, without even requiring them to be
true), it just hugely lowers the quality of implementation,
#ifdef FLAME
(but in the case of lcc-win32 it is difficult to make it much
lower than it would be, even without that spurious warning...)
#endif
but anyway lcc-win32 is broken for other reasons, too. (Choosing
an ISO C standard header at random, reading the one lcc-win32
provides, and failing to see anything wrong with it is not a very
easy task.)
--
Army1987 (Replace "NOSPAM" with "email")
A hamburger is better than nothing.
Nothing is better than eternal happiness.
Therefore, a hamburger is better than eternal happiness.

Eric Sosman

unread,
Sep 27, 2007, 8:26:38 AM9/27/07
to
jacob navia wrote:
>
> You mean then that
>
> int fn();
>
> is the same as
> int fn(void);
>
> ???

That's not the situation for which the compiler
issued the misleading messages.

int fn() { return 0; )

and

int fn(void) { return 0; }

define the fn function identically, even though they
declare it differently.

In a response to Francine Neary you write of the
original `int main() { ... }' that

> This is the definition of a function with an unspecified
> number of arguments.

... but that's wrong. The function is defined with no
arguments at all. It is declared as taking an unspecified
(fixed) number of arguments, but it is defined as taking
none. Would you maintain that

int main(argc, argv)
int argc;
char **argv;
{ ... }

... is the definition of a function with an unspecified
number of arguments?

Or again, consider a program of two compilation units:

/* module 1 */
int f(void);
int g();
int main(void) { return f() + g(); }

/* module 2 */
int f() { return 0; }
int g(void) { return 0; }

Is there a conflict between the declarations in module 1
and the definitions in module 2? If you see any, please
cite the relevant passage(s) from the Standard.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Sep 27, 2007, 8:37:08 AM9/27/07
to
jacob navia wrote:
>
> Under the highest warning level, a compiler should warn
> about
>
> int main()
>
> since it is an obsolete syntax. Note that lcc-win does NOT
> warn in the default warning level.

That is a reasonable goal, and I have no objection to
a compiler that issues a reasonable warning. But what would
you think of a compiler whose warning for this usage was

*** warning: possible loss of precision
or
*** warning: arguments to main() should be
declared `volatile'
or
*** warning: the Hundred Years' War actually
lasted 116 years

? I applaud the compiler's attempt to warn, but I deplore
its use of misleading or downright incorrect messages.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Ben Bacarisse

unread,
Sep 27, 2007, 8:38:47 AM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> writes:

> Francin...@googlemail.com wrote:
>>
>> But that wasn't what was in the original code. The original code went:
>>
>> int main()
>> {
>> ...
>> }
>>
>> In a function DEFINITION like this, () is completely equivalent to
>> (void) (I remember looking it up once...)
>>
>
> This is the definition of a function with an unspecified
> number of arguments.

You may have missed it because it is in the "wrong" place, but:

6.7.5.3 Function declarators (including prototypes)

states in paragraph 14:

An empty list in a function declarator that is part of a definition
of that function specifies that the function has no parameters. The


empty list in a function declarator that is not part of a

definition of that function specifies that no information about the


number or types of the parameters is supplied.

>> You're right that in a DECLARATION, they are different:


>>
>> int main(); /* main takes an unspecified number of parameters */
>> int main(void); /* main takes no parameters */
>>
>> So the warning is indeed bogus and incorrect. :)
>>
>
> I do not think so. But I am not a language lawyer.

Is it not an important skill for a compiler writer?

>> But a definition serves as a prototype. I'd expect this warning to
>> mean I'd called a function with no prototype in scope, which isn't the
>> case here.
>>
>
> This means that main has no prototype since you did NOT
> provide a prototype

Here I am with you.

6.9.1 Function definitions

states in paragraph 7:

The declarator in a function definition specifies the name of the
function being defined and the identifiers of its parameters. If the
declarator includes a parameter type list, the list also specifies
the types of all the parameters; such a declarator also serves as a


function prototype for later calls to the same function in the same

translation unit. If the declarator includes an identifier list,139)
the types of the parameters shall be declared in a following
declaration list. In either case, the type of each parameter is
adjusted as described in 6.7.5.3 for a parameter type list; the
resulting type shall be an object type.

This suggests to me that a function definition with no "parameter tpye
list" (note that int main() has an empty "identifier list" -- no the
same at all) is not a prototype. Given the special execption I quote
above it seems likely that this is a bug in the standard, but there it
is. I think you are right that int main() does not act as a prototype
for subsequent calls.

> and main *IS* always called!

Ah, but that is not the meaning of "for later calls to the same
function in the translation unit". You would be right to complain
about:

int main()
{
return main();
}

because the subsequent call has no prototype.

>>>>> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>>>> This warning is bogus and incorrect.
>>> The definition of main is int main(void) or int main(int,char **)
>>> not int main()
>>
>> Exactly as above... in a DEFINITION, int main() is absolutely fine.
>> (As in just main() in C90.)

It is an ANSI definition. int main(void) is OK but so are equivalent
forms and they snuck in a phrase that makes int main() equivalent. At
least that is my reading of it.

--
Ben.

Richard Bos

unread,
Sep 27, 2007, 8:42:36 AM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> wrote:

No, it isn't. It is obsolescent as a declaration. One may argue whether
it is obsolescent as the header of a _definition_ (you should really
know the difference) as well, but one cannot seriously argue that it is
already obsol_ete_, which is a rather stronger category than
obsol_escent_.

> Note that lcc-win does NOT warn in the default warning level.

So to avoid this bug in your software we have to avoid getting a strong
level of error checking. Nice. Sounds like Microsoft-quality software.
Remember that bug where their own headers triggered a warning?

Richard

Philip Potter

unread,
Sep 27, 2007, 8:53:41 AM9/27/07
to
jacob navia wrote:

> Philip Potter wrote:
>> int main() is ugly and obsolescent. But it is not (yet) incorrect.
>>
>
> Under the highest warning level, a compiler should warn
> about
>
> int main()
>
> since it is an obsolete syntax. Note that lcc-win does NOT
> warn in the default warning level.

I agree with you (pretending for the moment you said "obsolescent" and not

"obsolete"). But you said:

>>> gcc misses a warning for an incorrect definition
>>> of the 'main' function then.

It should *not* issue a warning for incorrect syntax, because the syntax is not
incorrect. It can issue a warning for obsolescent syntax if it likes.

Phil

Francin...@googlemail.com

unread,
Sep 27, 2007, 9:36:12 AM9/27/07
to
On Sep 27, 1:38 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> jacob navia <ja...@jacob.remcomp.fr> writes:
> > This means that main has no prototype since you did NOT
> > provide a prototype
>
> Here I am with you.
>
> 6.9.1 Function definitions
>
> states in paragraph 7:
>
> The declarator in a function definition specifies the name of the
> function being defined and the identifiers of its parameters. If the
> declarator includes a parameter type list, the list also specifies
> the types of all the parameters; such a declarator also serves as a
> function prototype for later calls to the same function in the same
> translation unit. If the declarator includes an identifier list,139)
> the types of the parameters shall be declared in a following
> declaration list. In either case, the type of each parameter is
> adjusted as described in 6.7.5.3 for a parameter type list; the
> resulting type shall be an object type.
>
> This suggests to me that a function definition with no "parameter tpye
> list" (note that int main() has an empty "identifier list" -- no the
> same at all) is not a prototype. Given the special execption I quote
> above it seems likely that this is a bug in the standard, but there it
> is. I think you are right that int main() does not act as a prototype
> for subsequent calls.

As I explained elsewhere, I read this differently. The key sentence is


"If the declarator includes a parameter type list, the list also
specifies the types of all the parameters; such a declarator also
serves as a function prototype for later calls to the same function in
the same translation unit."

What does it mean to "include a parameter type list"? Well, the
Standard tells us, in 6.5.4.3! It differentiates between a parameter
type list, which "specifies the types of the parameters of a
function", and an identifier list, which "declares only the
identifiers of the parameters of a function".

The seemingly ambiguous case is int main() { ... }. This could either
be regarded as main with an empty parameter-type-list, or main with a
non-supplied optional identifier-list. Which is it? Well, 6.5.4.3
comes to the rescue again and clears this up for us: for a function
DEFINITION, an empty list of parameters is interpreted in the first
way, specifying that the function has no parameters. (As it happens,
in a declaration that isn't a definition, it's interpreted in the
second way, giving no information about parameters, but that's
irrelevant here.)

Therefore, in the definition int main() { ... }, () is the empty
parameter-type-list, and therefore it serves as a function prototype
for later calls to main.

>
> > and main *IS* always called!
>
> Ah, but that is not the meaning of "for later calls to the same
> function in the translation unit". You would be right to complain
> about:
>
> int main()
> {
> return main();
>
> }
>
> because the subsequent call has no prototype.

No, as above.

Kenneth Brody

unread,
Sep 27, 2007, 9:56:51 AM9/27/07
to
Francin...@googlemail.com wrote:
>
> On Sep 27, 9:49 am, jacob navia <ja...@jacob.remcomp.fr> wrote:

[... "int main() { code }" versus "int main(void) { code } " ...]

> > > But a definition serves as a prototype. I'd expect this warning to
> > > mean I'd called a function with no prototype in scope, which isn't the
> > > case here.
> >
> > This means that main has no prototype since you did NOT
> > provide a prototype and main *IS* always called!
>
> (6.7.1) If the declarator includes a parameter type list... such a
> declarator also serves as a function prototype for later calls to the
> same function in the same translation unit.
>
> Now you need to observe that the empty list is a list...

[...]

Well, is my compiler broken then?

==========
#include <stdio.h>

int foo()
{
return 1;
}

int main(void)
{
foo();
foo(10);
}
==========

I get no warnings, even with warnings at the max. If I change the
"int foo()" to "int foo(void)", it warns me (even at the default
warning level) that "foo: declared with 'void' parameter list". If
you are saying that "int foo() { code }" does, in fact, prototype
foo() as having no parameters, then shouldn't my compiler warn me
about it, as it does when I explicitly state the void parameter list?

Now, I'm certainly not claiming that my compiler's output is the
gospel, just food for thought.

I'm curious what gcc with the "turn pedantry to the max" set of
switches says about the above?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:ThisIsA...@gmail.com>


jacob navia

unread,
Sep 27, 2007, 10:33:09 AM9/27/07
to

Nothing!

[root@gateway tmp]# gcc -Wall -pedantic t12.c
t12.c: In function `main':
t12.c:12: warning: control reaches end of non-void function
[root@gateway tmp]#

Ben Bacarisse

unread,
Sep 27, 2007, 11:35:11 AM9/27/07
to
Kenneth Brody <kenb...@spamcop.net> writes:

> Francin...@googlemail.com wrote:
>>
>> On Sep 27, 9:49 am, jacob navia <ja...@jacob.remcomp.fr> wrote:
>
> [... "int main() { code }" versus "int main(void) { code } " ...]
>
>> > > But a definition serves as a prototype. I'd expect this warning to
>> > > mean I'd called a function with no prototype in scope, which isn't the
>> > > case here.
>> >
>> > This means that main has no prototype since you did NOT
>> > provide a prototype and main *IS* always called!
>>
>> (6.7.1) If the declarator includes a parameter type list... such a
>> declarator also serves as a function prototype for later calls to the
>> same function in the same translation unit.
>>
>> Now you need to observe that the empty list is a list...
> [...]
>
> Well, is my compiler broken then?
>
> ==========
> #include <stdio.h>
>
> int foo()
> {
> return 1;
> }
>
> int main(void)
> {
> foo();
> foo(10);
> }
> ==========

Not broken, no.

> I get no warnings, even with warnings at the max. If I change the
> "int foo()" to "int foo(void)", it warns me (even at the default
> warning level) that "foo: declared with 'void' parameter list". If
> you are saying that "int foo() { code }" does, in fact, prototype
> foo() as having no parameters,

No. int foo() { code } is not a prototype for foo, so foo(10) is not a
constraint violation -- no diagnostic required. Gcc on max verbosity
tells me that the definition of foo does not constitute a prototype for
it which is certainly useful.

Function definitions like those of foo are peculiar. 6.7.5.3-14 (of
my non-authoritative draft) states that foo is a function that "has no
parameters" and 6.9.1-7 states that a definition only acts as
prototype if it includes a parameter list.

The call foo(10) is undefined due the wording in 6.5.2.2-6:

If the expression that denotes the called function has a type that
does not include a prototype, the integer promotions are performed
on each argument, and arguments that have type float are promoted
to double. These are called the default argument promotions. If the
number of arguments does not equal the number of parameters, the
behavior is undefined.

--
Ben.

jacob navia

unread,
Sep 27, 2007, 11:41:48 AM9/27/07
to

Then, the warning I am issuing is justified!


Ben Bacarisse

unread,
Sep 27, 2007, 12:00:21 PM9/27/07
to
Francin...@googlemail.com writes:

The syntax makes it quite clear, I think. See below...

>Well, 6.5.4.3
> comes to the rescue again and clears this up for us: for a function
> DEFINITION, an empty list of parameters is interpreted in the first
> way, specifying that the function has no parameters.

Yes but that section does not tell us how to disambiguate the () in
the function definition -- it tell us what it *means* but not what is
*is*. In fact it is not ambiguous if you look at the syntax. A
parameter type list may not be empty whereas an identifier list can
be. (Check for yourself, readers, because the syntax is complex and I
may well have got that wrong, though I have checked as carefully as I
can.)

I am open to persuasion (that int foo() { ... } acts as a prototype)
but you will have to persuade the gcc people as well! -- OK you need
to ask for -Wstrict-prototypes, but at least you can.

--
Ben.

Chris Hills

unread,
Sep 27, 2007, 12:35:13 PM9/27/07
to
In article <_bSdna2KqKqqB2bb...@bt.com>, Richard Heathfield
<r...@see.sig.invalid> writes

>Joachim Schmitz said:
>
>> "Richard Heathfield" <r...@see.sig.invalid> schrieb im Newsbeitrag
>> news:_bSdnbKKqKpsCmbb...@bt.com...
>>> I'd rather save
>>> pickiness for where it matters - such as, for example, not classifying
>>> the UK as part of Europe. The English Channel is there for a reason. :-)
>> You mean the Frensh Channel?
>
>Nope. I can read a map, same as anyone, and on my map of the universe it is
>clearly marked as the English Channel. I don't object to calling it the
>South Sea, though, if you'd prefer to do that.
>
>>
>> And believe it or nor, the UK is part of Europe, it is not a continent of
>> it's own and is even a member in the EU (still)
>
>I'm glad you think so. Just so long as Europe stays on its side of the
>water, you can think what you like. :-)

The sooner we get the Euro and fully integrated with Europe the better.
--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch...@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Francin...@googlemail.com

unread,
Sep 27, 2007, 1:18:57 PM9/27/07
to
On Sep 27, 5:00 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:

I don't have the energy to figure it out, but I'll take your word for
it... especially since, re-reading 6.5.4.3 in context, it does seem
that "empty list" refers to an empty identifier list.

So that's really ugly :(

int main() { ... } and int main(void) { ... } do indeed have very
subtly different semantics, which is dumb: after seeing either of them
the compiler knows exactly the signature of main, but only in one case
is it allowed to use this knowledge if it encounters main later in the
same translation unit. Yuck!

Harald van Dijk

unread,
Sep 27, 2007, 1:22:58 PM9/27/07
to
On Thu, 27 Sep 2007 05:07:00 -0400, Martin Ambuhl wrote:
> jacob navia wrote:
>> Martin Ambuhl wrote:
>>> Heinrich Pumpernickel wrote:
>>>> int main()
>>>> [...]

>>>> lcc -A -ansic -O long.c -o long.obj
>>>> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
>>> This warning is bogus and incorrect.
>>>
> There is nothing "old-style" about it.

6.11.6 Function declarators
1 The use of function declarators with empty parentheses (not prototype-


format parameter type declarators) is an obsolescent feature.

6.11.7 Function definitions
1 The use of function definitions with separate parameter identifier and
declaration lists (not prototype-format parameter type and identifier


declarators) is an obsolescent feature.

() in a function definition is the type of function definition having a
parameter identifier list, not a parameter declaration list. This is
specified by the grammar. I suppose you could try to argue that "old
style" is not the same as obsolescent, but:

6.7.5.3 Function declarators (including prototypes)

15 For two function types to be compatible, both shall specify compatible
return types.125) [...]
125) If both function types are "old style", parameter types are not
compared.

jacob navia

unread,
Sep 27, 2007, 1:24:55 PM9/27/07
to
Francin...@googlemail.com wrote:
> I don't have the energy to figure it out, but I'll take your word for
> it... especially since, re-reading 6.5.4.3 in context, it does seem
> that "empty list" refers to an empty identifier list.
>
> So that's really ugly :(
>
> int main() { ... } and int main(void) { ... } do indeed have very
> subtly different semantics, which is dumb: after seeing either of them
> the compiler knows exactly the signature of main, but only in one case
> is it allowed to use this knowledge if it encounters main later in the
> same translation unit. Yuck!
>
>> I am open to persuasion (that int foo() { ... } acts as a prototype)
>> but you will have to persuade the gcc people as well! -- OK you need
>> to ask for -Wstrict-prototypes, but at least you can.
>>
>> --
>> Ben.
>

OK Ben, then, you agree that a warning at the highest warning
level is justified!

Keith Thompson

unread,
Sep 27, 2007, 1:29:05 PM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> writes:
[...]
> Then, the warning I am issuing is justified!

Which one?

For context, here are the three warnings issued for 'int main() { ... }':

Warning c:\tmp\long.c: 4 old-style function definition for 'main'

Warning c:\tmp\long.c: 4 missing prototype for 'main'


Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition

The first warning is, IMHO, quite correct and reasonable. Note that
using parentheses for a function that takes no arguments is an easier
mistake to make than using a K&R-style definition with one or more
parameters. I suggest recognizing that special case and suggesting
changing '()' to '(void)'.

The second one is ok. A prototype is indeed missing, but the language
doesn't require a prototype. But if the compiler is invoked in a mode
that specifically requires prototypes, it's a valid warning.

The third one is simply incorrect. It says nothing that the first
warning didn't already tell you, and it's factually incorrect since
the ANSI^H^H^H^H ISO standard specifically allows old-style
declarations.

And *why* does the messsage refer to ANSI rather than ISO?

Keith Thompson

unread,
Sep 27, 2007, 1:33:32 PM9/27/07
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:
> Francin...@googlemail.com writes:
[...]

>> The seemingly ambiguous case is int main() { ... }. This could either
>> be regarded as main with an empty parameter-type-list, or main with a
>> non-supplied optional identifier-list. Which is it?
>
> The syntax makes it quite clear, I think. See below...
>
>>Well, 6.5.4.3
>> comes to the rescue again and clears this up for us: for a function
>> DEFINITION, an empty list of parameters is interpreted in the first
>> way, specifying that the function has no parameters.
>
> Yes but that section does not tell us how to disambiguate the () in
> the function definition -- it tell us what it *means* but not what is
> *is*. In fact it is not ambiguous if you look at the syntax. A
> parameter type list may not be empty whereas an identifier list can
> be. (Check for yourself, readers, because the syntax is complex and I
> may well have got that wrong, though I have checked as carefully as I
> can.)
>
> I am open to persuasion (that int foo() { ... } acts as a prototype)
> but you will have to persuade the gcc people as well! -- OK you need
> to ask for -Wstrict-prototypes, but at least you can.

Yes, the grammar is in 6.7.5:

parameter-type-list:
parameter-list
parameter-list , ...

parameter-list:
parameter-declaration
parameter-list , parameter-declaration

A parameter-type-list cannot be empty.

jacob navia

unread,
Sep 27, 2007, 1:42:40 PM9/27/07
to
Keith Thompson wrote:
> jacob navia <ja...@jacob.remcomp.fr> writes:
> [...]
>> Then, the warning I am issuing is justified!
>
> Which one?
>

The second one. The discussion is about the supposed difference
between () in a function declaration, where it means "indeterminate
number of parameters" and a function definition, where some people
here say the space between the () would be "overloaded" to mean
"void".

That interpretation is not correct IMHO.

> For context, here are the three warnings issued for 'int main() { ... }':
>
> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> Warning c:\tmp\long.c: 4 missing prototype for 'main'
> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
>
> The first warning is, IMHO, quite correct and reasonable. Note that
> using parentheses for a function that takes no arguments is an easier
> mistake to make than using a K&R-style definition with one or more
> parameters. I suggest recognizing that special case and suggesting
> changing '()' to '(void)'.
>
> The second one is ok. A prototype is indeed missing, but the language
> doesn't require a prototype. But if the compiler is invoked in a mode
> that specifically requires prototypes, it's a valid warning.
>
> The third one is simply incorrect. It says nothing that the first
> warning didn't already tell you, and it's factually incorrect since
> the ANSI^H^H^H^H ISO standard specifically allows old-style
> declarations.
>
> And *why* does the messsage refer to ANSI rather than ISO?
>


OK, will replace ANSI by ISO. I issue that third warning always
when I find a declaration of main that doesn't *exactly*
fit into int main(void) or int main(int argc,char *argv[])

At maximum warning level that is justified.

jacob navia

unread,
Sep 27, 2007, 1:43:50 PM9/27/07
to

That is confirmed in DR #317 as Harald van Dijk
told me in comp.std.c

Ben Bacarisse

unread,
Sep 27, 2007, 1:52:17 PM9/27/07
to
jacob navia <ja...@jacob.remcomp.fr> writes:

If you mean the "missing prototype" one, then I don't like the wording
because nothing is really missing (prototypes are not *required*) but it
does help a bit and it is not wrong. gcc says: "function declaration
isn’t a prototype" which is direct and to the point.

--
Ben.

jacob navia

unread,
Sep 27, 2007, 1:51:48 PM9/27/07
to
Francin...@googlemail.com wrote:
>> I am open to persuasion (that int foo() { ... } acts as a prototype)
>> but you will have to persuade the gcc people as well! -- OK you need
>> to ask for -Wstrict-prototypes, but at least you can.
>>
>> --
>> Ben.
>

The committee already discussed this question. Here is the answer:
------------------------------------------------------------------
Defect Report #317
Submitter: UK C Panel
Submission Date: 2005-03-04
Source: Joseph Myers <jos...@codesourcery.com>
Reference Document: ISO/IEC WG14 N1105
Version: 1.3
Date: 2006-04-04
Subject: Function definitions with empty parentheses

Summary

I believe the intent of C is that old-style function definitions with
empty parentheses do not give the function a type including a prototype
for the rest of the translation unit. For example,

void f(){}
void g(){if(0)f(1);}

is valid.

6.9.1#7 specifies that if the declarator in the function definition
includes a parameter type list, it also serves as a prototype for the
rest of the translation unit. It does not specify that nothing else
serves as a prototype. Some readers of the standard interpret
6.7.5.3#14, "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no
parameters.", as specifying that it provides a prototype.

Question 1: Does such a function definition give the function a type
including a prototype for the rest of the translation unit?

Question 2: Is the above translation unit valid?

Suggested Technical Corrigendum

Committee Response

The grammar states that an empty parens stands for an empty identifier
list not an empty parameter-type-list.

The answer to question #1 is NO, and to question #2 is YES. There are no
constraint violations, however, if the function call were executed it
would have undefined behavior. See 6.5.2.2;p6.

Chris Torek

unread,
Sep 27, 2007, 2:14:09 PM9/27/07
to
In article <1190913537.0...@19g2000hsx.googlegroups.com>

<Francin...@googlemail.com> wrote:
>int main() { ... } and int main(void) { ... } do indeed have very
>subtly different semantics ...

Yes: the latter provides a prototype declaration of the function
(in this case, of main()), as if one had written:

int main(void);
int main(void) { ... }

The former fails to provide a prototype declaration, only a
type-declaration, as if one had written:

int main();
int main() { ... }

>which is dumb: after seeing either of them the compiler knows
>exactly the signature of main, but only in one case is it allowed
>to use this knowledge if it encounters main later in the
>same translation unit. Yuck!

Change the word "allowed" to "required", and you have it precisely.

A compiler is always allowed to produce extra diagnostics. It
is only *required* to produce a diagnostic for this particular
error for a prototype mismatch. Hence, the code fragment:

/* x.c */
int f();
int g(void);

int h(void) {
return f(0) + g(0);
}

requires a diagnostic, because g(0) supplies an argument where the
compiler is required to remember that g() takes no arguments. If
the compiler can somehow tell that f() also takes no arguments --
e.g., by looking at a separate file like "f.c" or "f.o", or looking
elsewhere in this same file (x.c) and finding the actual code for
f(), or reading the design documentation for the project, or perhaps
even by reading the programmer's mind -- it is *allowed* to warn
about f().

(Writing a compiler that reads the project documentation and/or
the programmer's mind is perhaps a little ambitious. :-) Having
the compiler -- which includes the thing usually called "the linker",
in this case -- examine every file that is combined to make the
final executable is, however, quite feasible. The diagnostic for
the mismatch between an f() that takes no arguments and the call
f(0) may wind up looking something like "unable to find symbol
$function$int$f$int$", perhaps, although a "nice" linker might also
then back-translate that to "unable to find int f(int); I did find
an int f(void) but that does not match; perhaps the call at line
45 in h.c is incorrect".)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Eric Sosman

unread,
Sep 27, 2007, 3:06:51 PM9/27/07
to
jacob navia wrote On 09/27/07 13:42,:

> Keith Thompson wrote:
>
>>jacob navia <ja...@jacob.remcomp.fr> writes:
>>[...]
>>
>>>Then, the warning I am issuing is justified!
>>
>>Which one?
>>
>
>
> The second one. The discussion is about the supposed difference
> between () in a function declaration, where it means "indeterminate
> number of parameters" and a function definition, where some people
> here say the space between the () would be "overloaded" to mean
> "void".
>
> That interpretation is not correct IMHO.

Unless there are some other postings that haven't
reached my news server yet, yours is the first in this
thread to use the word "overloaded." No post that I
have seen has stated or implied that () and (void) are
equivalent, so I'm not sure who these "some people" are.

What I have claimed is that a function definition
like `int main()' defines a function with no parameters.
Others have claimed the same thing, and some have gone
so far as to quote the Standard's statement to that
effect. The quoted language is sufficiently direct that
there is little if any room for "interpretation."

--
Eric....@sun.com

jacob navia

unread,
Sep 27, 2007, 3:10:33 PM9/27/07
to
Eric Sosman wrote:
> jacob navia wrote On 09/27/07 13:42,:
>> Keith Thompson wrote:
>>
>>> jacob navia <ja...@jacob.remcomp.fr> writes:
>>> [...]
>>>
>>>> Then, the warning I am issuing is justified!
>>> Which one?
>>>
>>
>> The second one. The discussion is about the supposed difference
>> between () in a function declaration, where it means "indeterminate
>> number of parameters" and a function definition, where some people
>> here say the space between the () would be "overloaded" to mean
>> "void".
>>
>> That interpretation is not correct IMHO.
>
> Unless there are some other postings that haven't
> reached my news server yet, yours is the first in this
> thread to use the word "overloaded." No post that I
> have seen has stated or implied that () and (void) are
> equivalent, so I'm not sure who these "some people" are.
>
> What I have claimed is that a function definition
> like `int main()' defines a function with no parameters.

My warning was

"missing prototype for main()\n"

> Others have claimed the same thing, and some have gone
> so far as to quote the Standard's statement to that
> effect. The quoted language is sufficiently direct that
> there is little if any room for "interpretation."
>

No, the language is ambiguous and needed DR 317 to
clarify things. I am correct. There is NO prototype
for a function with () in the parameter list.

Harald van Dijk

unread,
Sep 27, 2007, 3:14:39 PM9/27/07
to
On Thu, 27 Sep 2007 21:10:33 +0200, jacob navia wrote:
> No, the language is ambiguous and needed DR 317 to clarify things.

No, the standard is unambiguous on () in function definitions, which is
why no changes were made as a result of the DR.

jacob navia

unread,
Sep 27, 2007, 3:19:17 PM9/27/07
to

Well, if that DR was needed it means that to be certain of the
unambiguous wording it was better to ask the question isn't it?

We have discussed here that at length with some citing this
and another citing that, and we could not get to a solution. OK,
after you say the answer of the committee, yes I believe it,
the wording is unambiguous ... :-)

Harald van Dijk

unread,
Sep 27, 2007, 5:06:20 PM9/27/07
to
On Thu, 27 Sep 2007 21:19:17 +0200, jacob navia wrote:
> Harald van Dijk wrote:
>> On Thu, 27 Sep 2007 21:10:33 +0200, jacob navia wrote:
>>> No, the language is ambiguous and needed DR 317 to clarify things.
>>
>> No, the standard is unambiguous on () in function definitions, which is
>> why no changes were made as a result of the DR.
>
> Well, if that DR was needed it means that to be certain of the
> unambiguous wording it was better to ask the question isn't it?

Yes, it means the standard is not as clear as it could (and possibly
should) be, but not more than that.

Eric Sosman

unread,
Sep 27, 2007, 3:52:49 PM9/27/07
to
jacob navia wrote On 09/27/07 15:10,:

> Eric Sosman wrote:
>
>>jacob navia wrote On 09/27/07 13:42,:
>>
>>>Keith Thompson wrote:
>>>
>>>
>>>>jacob navia <ja...@jacob.remcomp.fr> writes:
>>>>[...]
>>>>
>>>>
>>>>>Then, the warning I am issuing is justified!
>>>>
>>>>Which one?
>>>>
>>>
>>>The second one. The discussion is about the supposed difference
>>>between () in a function declaration, where it means "indeterminate
>>>number of parameters" and a function definition, where some people
>>>here say the space between the () would be "overloaded" to mean
>>>"void".
>>>
>>>That interpretation is not correct IMHO.
>>
>> Unless there are some other postings that haven't
>>reached my news server yet, yours is the first in this
>>thread to use the word "overloaded." No post that I
>>have seen has stated or implied that () and (void) are
>>equivalent, so I'm not sure who these "some people" are.
>>
>> What I have claimed is that a function definition
>>like `int main()' defines a function with no parameters.
>
>
> My warning was
>
> "missing prototype for main()\n"

That was one of them. Another was

> 'int main()' is a non-ANSI definition

... and the claim it makes is non-factual.

>>Others have claimed the same thing, and some have gone
>>so far as to quote the Standard's statement to that
>>effect. The quoted language is sufficiently direct that
>>there is little if any room for "interpretation."
>
> No, the language is ambiguous and needed DR 317 to
> clarify things.

There is no ambiguity. The committee reviewed the
report of the defect, responded that there was none (and
explained their reasoning), and closed the DR.

The fact that a defect report is filed does not prove
that a defect actually exists. Observe how strenuously
you yourself are denying any defect in lcc-win32 despite
the defect report that originated this very thread!

> I am correct. There is NO prototype
> for a function with () in the parameter list.

Nobody says there is. Furthermore, most posters agree
that *that* warning (issued twice, really) is reasonable.
It's the one about "non-ANSI" that's wrong. There is nothing
"non-ANSI" about `int main(){...}'. The ANSI Standard and
all its successors to date have all defined this construct,
have all agreed on its meaning, and have all agreed that it
is a valid definition of the `main' function for a hosted
environment.

The compiler may, of course, issue all the warnings
it wants. This particular warning is not "incorrect" in
the sense of contravening the language standard, but is
"incorrect" in the sense that it diminishes QoI. I urge
you to fix it in a future release (but I don't think it's
worth issuing a Mattel-style recall over it).

--
Eric....@sun.com

Kenneth Brody

unread,
Sep 27, 2007, 3:53:16 PM9/27/07
to
Ben Bacarisse wrote:
>
> Kenneth Brody <kenb...@spamcop.net> writes:
[...]

> > int foo()
> > {
> > return 1;
> > }
> >
> > int main(void)
> > {
> > foo();
> > foo(10);
> > }
[...]

> No. int foo() { code } is not a prototype for foo, so foo(10) is not a
> constraint violation -- no diagnostic required. Gcc on max verbosity
> tells me that the definition of foo does not constitute a prototype for
> it which is certainly useful.

I wouldn't consider it a prototype, either. However, somewhere
elsethread, I got the impression that people were arguing that
"int main() {...}" constituted a prototype equivalent to
"int main(void)". Specifically, they were complaining that lcc
was issuing a warning.

[...]

Keith Thompson

unread,
Sep 27, 2007, 4:49:13 PM9/27/07
to
Francin...@googlemail.com writes:
[...]

> I don't have the energy to figure it out, but I'll take your word for
> it... especially since, re-reading 6.5.4.3 in context, it does seem
> that "empty list" refers to an empty identifier list.
>
> So that's really ugly :(
>
> int main() { ... } and int main(void) { ... } do indeed have very
> subtly different semantics, which is dumb: after seeing either of them
> the compiler knows exactly the signature of main, but only in one case
> is it allowed to use this knowledge if it encounters main later in the
> same translation unit. Yuck!

Yes, but it's a necessary ugliness. See my explanation in comp.std.c.

Keith Thompson

unread,
Sep 27, 2007, 5:06:05 PM9/27/07
to

Yes, given

int main() { /* ... */ }

there is no prototype. Your warning about a "missing prototype" is
ok; the word "missing" could imply that a prototype is required, which
is not the case, but since the warning is only issued at a high
diagnostic level where the user in effect asked for prototypes to be
required, I won't quibble about it. (Well, not much.)

I think one person in this discussion said or implied that there is a
prototype in that case. That person was mistaken, and you were right.
(You might want to consider not making quite such a big deal about
that fact; you probably don't want to imply that your being right
about something is an unusual occasion.)

But that is not the only thing we're discussing. Another of the three
(!) warnings you issue for that line says that the declaration is
"non-ANSI". That is clearly and unambiguously incorrect. Functions
without prototypes are obsolescent, but they are not obsolete; they
are just as much a part of the ANSI/ISO standard (C89, C90, C95, or
C99) as prototypes. Warning about an unprototyped function is fine,
but *please* make sure that the warning message itself is factually
correct.

An argument can be made that 'int main() { /* ... */ }' is invalid in
C90 and C99 (specifically that it invokes undefined behavior unless
the implementation documents it as an allowed form), but on further
examination I'm 99% convinced that the intent is for it to be valid
(i.e., that a conforming compiler may not reject it). I've discussed
this at greater length in comp.std.c.

Keith Thompson

unread,
Sep 27, 2007, 5:24:34 PM9/27/07
to
Kenneth Brody <kenb...@spamcop.net> writes:
[...]
> I wouldn't consider it a prototype, either. However, somewhere
> elsethread, I got the impression that people were arguing that
> "int main() {...}" constituted a prototype equivalent to
> "int main(void)". Specifically, they were complaining that lcc
> was issuing a warning.

They were wrong.

The two are equivalent *as definitions*, in that they both define main
as a function with no parameters. But they differ *as declarations*,
in that the old-style non-prototype '()' form doesn't cause incorrect
calls to be constraint violations.

Old Wolf

unread,
Sep 27, 2007, 7:29:16 PM9/27/07
to
On Sep 27, 8:10 pm, Philip Potter <p...@see.sig.invalid> wrote:
>
> int main() is ugly and obsolescent.

It is not ugly to me. The function takes no arguments so
there is nothing inside the parentheses. That's how it is
in almost every other programming language that has
functions.

Requiring text to indicate lack of parameters is ugly.

Keith Thompson

unread,
Sep 27, 2007, 8:33:42 PM9/27/07
to

And necessary given the need for backward compatibility with pre-ANSI
C.

U

unread,
Sep 27, 2007, 9:19:09 PM9/27/07
to
[crossposted to comp.compilers.lcc]

In comp.lang.c, Heinrich Pumpernickel wrote:

> what does this warning mean ?
>
>
> #include <stdio.h>
>
> int main()
> {
> long l = 100;
>
> printf("l is %li\n", l * 10L);
>
> return 0;
> }
>
>
> when i compile this program with lcc-win32 it prints


>
> lcc -A -ansic -O long.c -o long.obj

> Warning c:\tmp\long.c: 4 old-style function definition for 'main'
> Warning c:\tmp\long.c: 4 missing prototype for 'main'

> Warning c:\tmp\long.c: 4 'int main()' is a non-ANSI definition
> Warning c:\tmp\long.c: 7 printf argument mismatch for format i.
> Expected long int got int
> 0 errors, 4 warnings

[snip]

<OT group="c.l.c">

One thing I observed a long time ago is that lcc-win32 sometimes
produces warnings for operations on signed types but not for the
same operations on unsigned types.

*long -> *int ==> diagnostic
*unsigned long -> *unsigned int ==> no diagnostic

The same seems to be true for printf() arguments as well,

long l; unsigned long ul;
printf("%li\n", l * 10); ==> diagnostic
printf("%lu\n", lu * 10); ==> no diagnostic


/*** begin lcctest.c ***/

#include <stdio.h>

volatile void *foo;

int main(void)
{
long l = 100;
unsigned long ul = 100;

int *pi = &l; /* line 12: produces diagnostic */
unsigned int *pui = &ul; /* line 13: no diagnostic */

/* prevent prev. two statements from being optimized away */
foo = pi; foo = pui;

printf(" l * 10: %li\n", l * 10);
printf(" ul * 10: %lu\n", ul * 10);

return 0;
}

/*** end lcctest.c ***/

$ wine lcc -ansic -A -O lcctest.c
Warning z:\src\clc\lcctest.c: 12 assignment of pointer to long int to
pointer to int
Warning z:\src\clc\lcctest.c: 18 printf argument mismatch for format i.
Expected long int got int
0 errors, 2 warnings

</OT>

somenath

unread,
Sep 28, 2007, 1:29:52 AM9/28/07
to
On Sep 27, 11:14 pm, Chris Torek <nos...@torek.net> wrote:
> In article <1190913537.007633.323...@19g2000hsx.googlegroups.com>

>
> <Francine.Ne...@googlemail.com> wrote:
> >int main() { ... } and int main(void) { ... } do indeed have very
> >subtly different semantics ...
>
> Yes: the latter provides a prototype declaration of the function
> (in this case, of main()), as if one had written:
>
> int main(void);
> int main(void) { ... }
>
> The former fails to provide a prototype declaration, only a
> type-declaration, as if one had written:
>
> int main();
> int main() { ... }
>
> >which is dumb: after seeing either of them the compiler knows
> >exactly the signature of main, but only in one case is it allowed
> >to use this knowledge if it encounters main later in the
> >same translation unit. Yuck!
>
> Change the word "allowed" to "required", and you have it precisely.
>
> A compiler is always allowed to produce extra diagnostics. It
> is only *required* to produce a diagnostic for this particular
> error for a prototype mismatch. Hence, the code fragment:
>
> /* x.c */
> int f();
> int g(void);
>
> int h(void) {
> return f(0) + g(0);
> }
>

I am little confuse about the example


> requires a diagnostic, because g(0) supplies an argument where the
> compiler is required to remember that g() takes no arguments.

While I compile with gcc as
I get the bellow mentioned warnings
gcc -Wall x.c
x.c: In function `h':
x.c:12: too many arguments to function `g'

This I can undersatnd as it is explained in the above sentences .


>If
> the compiler can somehow tell that f() also takes no arguments --
> e.g., by looking at a separate file like "f.c" or "f.o", or looking
> elsewhere in this same file (x.c) and finding the actual code for
> f(), or reading the design documentation for the project, or perhaps
> even by reading the programmer's mind -- it is *allowed* to warn
> about f().
>
> (Writing a compiler that reads the project documentation and/or
> the programmer's mind is perhaps a little ambitious. :-) Having
> the compiler -- which includes the thing usually called "the linker",
> in this case -- examine every file that is combined to make the
> final executable is, however, quite feasible. The diagnostic for
> the mismatch between an f() that takes no arguments and the call
> f(0) may wind up looking something like "unable to find symbol
> $function$int$f$int$", perhaps, although a "nice" linker might also
> then back-translate that to "unable to find int f(int); I did find
> an int f(void) but that does not match; perhaps the call at line
> 45 in h.c is incorrect".)

But If I change the code as mentioned bellow

#include<stdio.h>

int f();
int g(void);

int main(void)
{
return 0;
}

int h(void) {
return f() + g();
}

I get the linker error as

gcc -Wall x.c
/tmp/cc6rowkR.o(.text+0x1f): In function `h':
: undefined reference to `f'
/tmp/cc6rowkR.o(.text+0x26): In function `h':
: undefined reference to `g'
collect2: ld returned 1 exit status

could you please let me know why it is throwing such errors ?


Stephen Sprunk

unread,
Sep 28, 2007, 1:46:20 AM9/28/07
to
"somenath" <somen...@gmail.com> wrote in message
news:1190957392.7...@r29g2000hsg.googlegroups.com...

> But If I change the code as mentioned bellow
>
> #include<stdio.h>
>
> int f();
> int g(void);
>
> int main(void)
> {
> return 0;
> }
>
> int h(void) {
> return f() + g();
> }
>
> I get the linker error as
>
> gcc -Wall x.c
> /tmp/cc6rowkR.o(.text+0x1f): In function `h':
> : undefined reference to `f'
> /tmp/cc6rowkR.o(.text+0x26): In function `h':
> : undefined reference to `g'
> collect2: ld returned 1 exit status
>
> could you please let me know why it is throwing such errors ?

You declared the functions, but you did not define them, i.e. there is no
body to your functions available. If you had enabled optimization, gcc
might have removed f(), g(), and h() entirely since they're never called
from main().

<OT>
"undefined reference to 'foo'" is almost always ld telling you that you
forgot to define the named function or link in a required library that
contains said function. If you only want to check for compilation errors
without trying to link, add "-c" to the gcc command line.
</OT>

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking


--
Posted via a free Usenet account from http://www.teranews.com

Richard Bos

unread,
Sep 28, 2007, 2:23:12 AM9/28/07
to
Chris Hills <ch...@phaedsys.org> wrote:

> In article <_bSdna2KqKqqB2bb...@bt.com>, Richard Heathfield
> <r...@see.sig.invalid> writes
> >Joachim Schmitz said:
> >
> >> And believe it or nor, the UK is part of Europe, it is not a continent of
> >> it's own and is even a member in the EU (still)
> >
> >I'm glad you think so. Just so long as Europe stays on its side of the
> >water, you can think what you like. :-)
>
> The sooner we get the Euro and fully integrated with Europe the better.

One one condition: that you get out of the United States of America.

Richard

John J. Smith

unread,
Sep 28, 2007, 9:49:05 AM9/28/07
to
U wrote:
[followup set to c.l.c]

Um... wouldn't line 13 be a constraint violation and every
conforming compiler is *required* to issue a diagnostic even
when not at the highest warning level? (even warning about
line 12 is not issued without "-A".)

I have extended your test with some suspicious pointer
assignments involving 'char' and no diagnostic is issued for
those either, even at the highest warning level.

Gcc warns about lines 12, 13, 14, and 15.

Which of those are really required by the standard?


Modified test and compiler output follows.

/*** begin lcctest.c (modified by jss) ***/

#include <stdio.h>

volatile void *foo;

int main(void)
{
long l = 100;
unsigned long ul = 100;

char c = 1;

int *pi = &l; /* line 12 */
unsigned int *pui = &ul; /* line 13 */
signed char *psc = &c; /* line 14 */
unsigned char *puc = &c; /* line 15 */

/* prevent prev. two statements from being optimized away */

foo = pi; foo = pui; foo = psc; foo = puc;

printf(" l * 10: %li\n", l * 10);
printf(" ul * 10: %lu\n", ul * 10);

return 0;
}

/*** end lcctest.c ***/

lcc output:

$ wine lcc -ansic -A -O lcctest.c

Warning z:\home\jss\src\clc\lcctest.c: 14 assignment of pointer to long int
to pointer to int
Warning z:\home\jss\src\clc\lcctest.c: 22 printf argument mismatch for


format i. Expected long int got int
0 errors, 2 warnings

gcc output:

$ gcc-4.2 -Wall -W -ansi -pedantic -O2 -c lcctest.c
lcctest.c: In function 'main':
lcctest.c:13: warning: initialization from incompatible pointer type
lcctest.c:14: warning: initialization from incompatible pointer type
lcctest.c:15: warning: pointer targets in initialization differ in
signedness
lcctest.c:16: warning: pointer targets in initialization differ in
signedness


--
John J. Smith
(Just Curious)

jacob navia

unread,
Sep 28, 2007, 10:43:52 AM9/28/07
to
John J. Smith wrote:
>
> gcc output:
>
> $ gcc-4.2 -Wall -W -ansi -pedantic -O2 -c lcctest.c
> lcctest.c: In function 'main':
> lcctest.c:13: warning: initialization from incompatible pointer type
> lcctest.c:14: warning: initialization from incompatible pointer type
> lcctest.c:15: warning: pointer targets in initialization differ in
> signedness
> lcctest.c:16: warning: pointer targets in initialization differ in
> signedness
>
>

MSVC++ says:
------------------------------------------------
twarn1.c(11) : warning C4057: 'initializing' : 'int *' differs in
indirection to slightly
different base types from 'long *'
twarn1.c(12) : warning C4057: 'initializing' : 'unsigned int *' differs
in indirection to
slightly different base types from 'unsigned long *'
twarn1.c(14) : warning C4057: 'initializing' : 'unsigned char *' differs
in indirection to
slightly different base types from 'char *'
-----------------------------------------------
only at the highest warning level (-W4)

At the default level absolutely NO warnings are issued.

I am ready to change the compiler if any contradiction
to the standard is detected. I do not see here why a
warning is mandatory however.

jacob

Chris Hills

unread,
Sep 28, 2007, 11:46:27 AM9/28/07
to
In article <46fc9db9....@news.xs4all.nl>, Richard Bos
<r...@hoekstra-uitgeverij.nl> writes

Absolutely!.... I couldn't agree more . Though the US can keep Blair
--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch...@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Kenneth Brody

unread,
Sep 28, 2007, 1:34:21 PM9/28/07
to
Eric Sosman wrote:
[...]

> There is no ambiguity. The committee reviewed the
> report of the defect, responded that there was none (and
> explained their reasoning), and closed the DR.
>
> The fact that a defect report is filed does not prove
> that a defect actually exists. Observe how strenuously
> you yourself are denying any defect in lcc-win32 despite
> the defect report that originated this very thread!
[...]

I would expect most software developers to know the difference between
a "defect report" and a "defect". The general populace, on the other
hand...

The company I work for used to keep a list of "bug reports" and their
status publicly available on the website. This stopped when TPTB at
the company that bought the company objected, stating that they were
getting complaints along the line of "why would be buy a software
package with 600 bugs?"

The fact that this list included all reports, including real bugs
that were fixed long ago, as well as non-bugs[1], seemed to elude
some people. Adding a disclaimer to that effect wasn't enough for
TPTB, and the list was removed from the publicly accessible part of
the site.


[1] We would get "bug reports" on things like "isleap() says that
the year 2000 is a leap year", or "on a DT-100 terminal, the
vertical lines don't connect", or things that were simply
pure user error. These were all included in the list.

Keith Thompson

unread,
Sep 28, 2007, 4:12:13 PM9/28/07
to
Chris Hills <ch...@phaedsys.org> writes:
> In article <46fc9db9....@news.xs4all.nl>, Richard Bos
> <r...@hoekstra-uitgeverij.nl> writes
>>Chris Hills <ch...@phaedsys.org> wrote:
>>
>>> In article <_bSdna2KqKqqB2bb...@bt.com>, Richard Heathfield
>>> <r...@see.sig.invalid> writes
>>> >Joachim Schmitz said:
>>> >
>>> >> And believe it or nor, the UK is part of Europe, it is not a
>>> >> continent of it's own and is even a member in the EU (still)
>>> >
>>> >I'm glad you think so. Just so long as Europe stays on its side of the
>>> >water, you can think what you like. :-)
>>>
>>> The sooner we get the Euro and fully integrated with Europe the better.
>>
>>One one condition: that you get out of the United States of America.
>
> Absolutely!.... I couldn't agree more . Though the US can keep Blair

<SARCASM>
Yes, an international political debate is *exactly* what this
newsgroup needs.
</SARCASM>

Followups redirected.

jacob navia

unread,
Sep 28, 2007, 5:30:38 PM9/28/07
to
Keith Thompson wrote:

>
> <SARCASM>
> Yes, an international political debate is *exactly* what this
> newsgroup needs.
> </SARCASM>
>


Yes, Let's go back to what they were discussing before... What was it?

Ahhh yes!

Why jacob is a "Frog".

Very on topic!

Mark McIntyre

unread,
Sep 28, 2007, 7:03:18 PM9/28/07
to
On Thu, 27 Sep 2007 10:49:18 +0200, in comp.lang.c , jacob navia
<ja...@jacob.remcomp.fr> wrote:

>Francin...@googlemail.com wrote:
>>
>> But that wasn't what was in the original code. The original code went:
>>
>> int main()

>
>This is the definition of a function with an unspecified
>number of arguments.

No. This is the definition of a function with _no_ arguments.

>> So the warning is indeed bogus and incorrect. :)
>
>I do not think so. But I am not a language lawyer.

Well you bloody well should be, if you intend to claim you have
written a C compiler. Good grief.

>This means that main has no prototype since you did NOT
>provide a prototype and main *IS* always called!

Note that
a) main is not required to have a prototype; and
b) a function definition _is_ a prototype, if no previous prototype
has been provided, and provided it has parameters - see 6.9.1 .

In my view, whatever else is the case, since main is not required to
have a prototype, it is simply misleading to generate errors
suggesting otherwise.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan

Eric Sosman

unread,
Sep 28, 2007, 11:08:08 PM9/28/07
to
Kenneth Brody wrote:
> [...]

> [1] We would get "bug reports" on things like "isleap() says that
> the year 2000 is a leap year", [...]

The response to that one was a classic. It circulated
widely on the Net even before there was a Web, and can still
be found: Google "11-60903".

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Sep 28, 2007, 11:09:50 PM9/28/07
to

"It's not that easy bein' green." -- K

--
Eric Sosman
eso...@ieee-dot-org.invalid

jacob navia

unread,
Sep 29, 2007, 3:45:28 AM9/29/07
to
Mark McIntyre wrote:
> On Thu, 27 Sep 2007 10:49:18 +0200, in comp.lang.c , jacob navia
> <ja...@jacob.remcomp.fr> wrote:
>
>> Francin...@googlemail.com wrote:
>>> But that wasn't what was in the original code. The original code went:
>>>
>>> int main()
>
>> This is the definition of a function with an unspecified
>> number of arguments.
>
> No. This is the definition of a function with _no_ arguments.
>

If I write

int foo() { return 5; }

int main() { foo(10); }

neither MSVC nor gcc will complain even at the HIGHEST
warning level (Wall -W4 respectively) ???

Because the function definition of foo DOES NOT GIVE A PROTOTYPE
as specified in the Defect Report 317 where the question was
explicitly posed to the standard committee that clearly answered:
NO, there is NO prototype produced by
int foo()

So you are just WRONG.

>>> So the warning is indeed bogus and incorrect. :)
>> I do not think so. But I am not a language lawyer.
>
> Well you bloody well should be, if you intend to claim you have
> written a C compiler. Good grief.
>

I am correct according to DR 317.

And I am still not a lawyer.


Charlie Gordon

unread,
Sep 28, 2007, 1:59:22 PM9/28/07
to
"jacob navia" <ja...@jacob.remcomp.fr> a écrit dans le message de news:
46fd1371$0$25924$ba4a...@news.orange.fr...

Microsoft is not a good example to follow (most of the regulars think it's
obvious, but in this case it is blatant).

When they moved from 16 to 32 bits with the Win32 API, back in 1993, they
made int and LONG the same size, but engraved WORD and LONG as 16 and 32
bits in memory and file based data structures. Since then, there has been a
growing confusion between these two types, and they never prevented it with
appropriate warnings in their tools. Pretending that 'unsigned int *' and
unsigned long *' be just indirections to *slightly* different base types is
calling for a beating.

No surprise, when came time to make choices for a Win64 API, the confusion
had settled in so deeply into every corner of the API that it was hopeless
to try and change the size of any of these types. As far as Windows is
concerned, int and long and LONG will remain 32 bits forever, while size_t
became 64 bits (unsigned long long), yuk!.

You seem to make the same confusion: you consider int and long to be
typedefs to the same int32_t base type, and quickly lose sight of the actual
original type. This is a bogus approximation that does not work for border
cases. I don't know if the original lcc had this approach, but as was
demonstrated elsethread, it produces a non-conformant (aka broken) compiler.

I have no idea how difficult it would be to fix this in lcc-win32, only you
know.

--
Chqrlie.


Mark McIntyre

unread,
Sep 29, 2007, 7:42:29 AM9/29/07
to
On Sat, 29 Sep 2007 09:45:28 +0200, in comp.lang.c , jacob navia
<ja...@jacob.remcomp.fr> wrote:

>Mark McIntyre wrote:

>> No. This is the definition of a function with _no_ arguments.
>

>....the function definition of foo DOES NOT GIVE A PROTOTYPE

>So you are just WRONG.

Apparently as well as being not a language lawyer, you also can't
read.

I did not say it was a prototype.

>I am correct according to DR 317.

DR 317 relates to whether or not the definition void f() {} is a
prototype. Its not. I have not said otherwise. I've said it defines a
function with no arguments.

jacob navia

unread,
Sep 29, 2007, 8:23:38 AM9/29/07
to
Mark McIntyre wrote:
> On Sat, 29 Sep 2007 09:45:28 +0200, in comp.lang.c , jacob navia
> <ja...@jacob.remcomp.fr> wrote:
>
>> Mark McIntyre wrote:
>
>>> No. This is the definition of a function with _no_ arguments.
>> ....the function definition of foo DOES NOT GIVE A PROTOTYPE
>
>> So you are just WRONG.
>
> Apparently as well as being not a language lawyer, you also can't
> read.
>
> I did not say it was a prototype.
>
>> I am correct according to DR 317.
>
> DR 317 relates to whether or not the definition void f() {} is a
> prototype. Its not. I have not said otherwise. I've said it defines a
> function with no arguments.
>

Yes a function with no arguments and no prototype.
THAT IS WHY MY WARNING IS:

missing prototype for "foo".

Mark McIntyre

unread,
Sep 29, 2007, 8:49:58 AM9/29/07
to

However I was commenting on your statement that foo() {} defined a


function with an unspecified number of arguments.

If you want to retract the statement, this is probably a good time.

Keith Thompson

unread,
Sep 29, 2007, 3:45:41 PM9/29/07
to
jacob navia <ja...@jacob.remcomp.fr> writes:
> Mark McIntyre wrote:
>> On Thu, 27 Sep 2007 10:49:18 +0200, in comp.lang.c , jacob navia
>> <ja...@jacob.remcomp.fr> wrote:
>>> Francin...@googlemail.com wrote:
>>>> But that wasn't what was in the original code. The original code went:
>>>>
>>>> int main()
>>
>>> This is the definition of a function with an unspecified
>>> number of arguments.
>> No. This is the definition of a function with _no_ arguments.
>
> If I write
>
> int foo() { return 5; }
>
> int main() { foo(10); }
>
> neither MSVC nor gcc will complain even at the HIGHEST
> warning level (Wall -W4 respectively) ???
>
> Because the function definition of foo DOES NOT GIVE A PROTOTYPE
> as specified in the Defect Report 317 where the question was
> explicitly posed to the standard committee that clearly answered:
> NO, there is NO prototype produced by
> int foo()
>
> So you are just WRONG.
[snip]

jacob, *please* calm down. Your habit of (figuratively) jumping up
and down and shouting whenever you think you're right and somebody
else is wrong comes across as being quite childish. We all make
mistakes here. I often correct other people's mistakes, and other
people often correct my mistakes. Most of the time, it's done calmly
and politely, and I'm grateful when someone points out that I've
gotten something wrong. You're acting as if your being right is a
rare event, a cause for celebration; I really don't think that's the
impression you want to convey.

Now I suggest you re-read the above very carefully. Part of the
context was snipped; the orginal example was:

int main()
{
...
}

You said that this is the definition of a function with an unspecified
number of arguments. You were mistaken. Mark said that it's the
definition of a function with no arguments. Apart from the use of the
word "arguments" rather than "parameters", he was right. It defines a
function with no parameters. If you don't believe me, try writing
some code to replace the '..." that refers to a parameter of main.

It's true that the above definition does not provide a prototype for
main (but Mark never said that it does). It's true that, since there
is no prototype, compilers typically do not diagnose calls that
attempt to pass extra arguments (but Mark never said that they do).

The above definition *defines* main as a function with no parameters,
but it *declares* main as a function with an unspecified number and
type of parameters. I presume I don't have to explain to you the
difference between a declaration and a definition.

Mark was right. You were right in some of the things you wrote, but
you were wrong in asserting that Mark was wrong; you refuted things
that he never said.

Keith Thompson

unread,
Sep 29, 2007, 3:56:09 PM9/29/07
to
"Charlie Gordon" <ne...@chqrlie.org> writes:
[...]

> Microsoft is not a good example to follow (most of the regulars think it's
> obvious, but in this case it is blatant).
>
> When they moved from 16 to 32 bits with the Win32 API, back in 1993, they
> made int and LONG the same size, but engraved WORD and LONG as 16 and 32
> bits in memory and file based data structures. Since then, there has been a
> growing confusion between these two types, and they never prevented it with
> appropriate warnings in their tools. Pretending that 'unsigned int *' and
> unsigned long *' be just indirections to *slightly* different base types is
> calling for a beating.

Does MS really define a type LONG, distinct from long, or did you put
LONG in all-caps for emphasis?

[...]

> You seem to make the same confusion: you consider int and long to be
> typedefs to the same int32_t base type, and quickly lose sight of the actual
> original type. This is a bogus approximation that does not work for border
> cases. I don't know if the original lcc had this approach, but as was
> demonstrated elsethread, it produces a non-conformant (aka broken) compiler.
>
> I have no idea how difficult it would be to fix this in lcc-win32, only you
> know.

My understanding, based on what jacob has posted here, is that
lcc-win32 treats int and long as the same type only in later parts of
its analysis. Actual type conflicts, such as assigning an int* to a
long*, are correctly caught because that checking is done early. The
(non-required) checking of printf format is done later, which is what
led to the bug we've been discussing here. (I'm using the word "bug"
in this case, to refer to a false statement in a warning message, not
to any non-conformance.)

I don't *think* it's been demostrated here that lcc-win32 does
anything non-conforming as a result of its conflating of int and long.

Now if I were writing a compiler from scratch, I would maintain int
and long as separate types through all processing phases. The
internal compiler data structures that describe those types might
include referenes to some common machine-level information. For
example, there might be an internal "WORD" pseudo-type. The
pseudo-type WORD would be used only for code generation; everything
visible to the user, particularly diagnostic messages, would refer to
the language-defined types int and long, which would remain distinct.

I don't intend this as a criticism of lcc-win32; I'm just thinking out
loud about the best way to structure a compiler to avoid problems like
the ones we've seen here.

pete

unread,
Sep 29, 2007, 4:59:45 PM9/29/07
to

You might have to.

> Mark was right. You were right in some of the things you wrote, but
> you were wrong in asserting that Mark was wrong; you refuted things
> that he never said.

Mark was righter than that.
jacob navia even quoted Mark's
explanation of the point of confusion,
and then disagreed with it,
and then followed the diagreement with something
that almost looks like an apology:

"> You're right that in a DECLARATION, they are different:
>
> int main(); /* main takes an unspecified number of parameters */
> int main(void); /* main takes no parameters */


>
> So the warning is indeed bogus and incorrect. :)
>

I do not think so. But I am not a language lawyer.
"

--
pete

Mark McIntyre

unread,
Sep 29, 2007, 6:20:23 PM9/29/07
to
On Sat, 29 Sep 2007 12:56:09 -0700, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>Does MS really define a type LONG, distinct from long, or did you put
>LONG in all-caps for emphasis?

MS define a whole slew of types in ALL CAPS, including LONG. .

Charlie Gordon

unread,
Sep 30, 2007, 8:36:29 AM9/30/07
to
"Keith Thompson" <ks...@mib.org> a écrit dans le message de news:
lnd4w1k...@nuthaus.mib.org...

> "Charlie Gordon" <ne...@chqrlie.org> writes:
> [...]
>> Microsoft is not a good example to follow (most of the regulars think
>> it's
>> obvious, but in this case it is blatant).
>>
>> When they moved from 16 to 32 bits with the Win32 API, back in 1993, they
>> made int and LONG the same size, but engraved WORD and LONG as 16 and 32
>> bits in memory and file based data structures. Since then, there has
>> been a
>> growing confusion between these two types, and they never prevented it
>> with
>> appropriate warnings in their tools. Pretending that 'unsigned int *'
>> and
>> unsigned long *' be just indirections to *slightly* different base types
>> is
>> calling for a beating.
>
> Does MS really define a type LONG, distinct from long, or did you put
> LONG in all-caps for emphasis?

As was already mentioned elsethread, MS typedefs a truckload of all caps
types such as BYTE, WORD, LONG and DWORD intrinsically hard-wired for widths
of 8, 16 and 32 bits. After 20 years of brainwashing, it was impossible to
change the width of LONG or long for the WIN64 architecture.

> [...]
>
>> You seem to make the same confusion: you consider int and long to be
>> typedefs to the same int32_t base type, and quickly lose sight of the
>> actual
>> original type. This is a bogus approximation that does not work for
>> border
>> cases. I don't know if the original lcc had this approach, but as was
>> demonstrated elsethread, it produces a non-conformant (aka broken)
>> compiler.
>>
>> I have no idea how difficult it would be to fix this in lcc-win32, only
>> you
>> know.
>
> My understanding, based on what jacob has posted here, is that
> lcc-win32 treats int and long as the same type only in later parts of
> its analysis. Actual type conflicts, such as assigning an int* to a
> long*, are correctly caught because that checking is done early. The
> (non-required) checking of printf format is done later, which is what
> led to the bug we've been discussing here. (I'm using the word "bug"
> in this case, to refer to a false statement in a warning message, not
> to any non-conformance.)

Yes, I agree.

> I don't *think* it's been demostrated here that lcc-win32 does
> anything non-conforming as a result of its conflating of int and long.

Not exactly from conflating int and long, but from general confusion of
integer types: in a thread early this month (Re: Visual C++ Express Edition
or lcc-win32?) someone pointed out that some of the definitions in stdin.h
were incorrect:

#define INT8_MIN -128
#define INT16_MIN -32768
#define INT32_MIN -2147483648

Jacob probably corrected the missing parentheses by now, but the issue is
more sublte:

-2147483648 is a long long in C99, but lcc-win32 treats it as an int/long:

sizeof -2147483648 should evaluate to 8, but it produces 4.

The correct definition of INT_MIN should be:

#define INT_MIN (-2147483647 - 1) or
#define INT_MIN (-INT_MAX - 1)

> Now if I were writing a compiler from scratch, I would maintain int
> and long as separate types through all processing phases. The
> internal compiler data structures that describe those types might
> include referenes to some common machine-level information. For
> example, there might be an internal "WORD" pseudo-type. The
> pseudo-type WORD would be used only for code generation; everything
> visible to the user, particularly diagnostic messages, would refer to
> the language-defined types int and long, which would remain distinct.
>
> I don't intend this as a criticism of lcc-win32; I'm just thinking out
> loud about the best way to structure a compiler to avoid problems like
> the ones we've seen here.

Neither do I, I would gladly help Jacob if his compiler was open source.
btw. open source does not have to mean free (as in free speech), nor free
(as in free beer), which lcc-win32 is already for non-commercial use.

--
Chqrlie.


Army1987

unread,
Sep 30, 2007, 8:40:53 AM9/30/07
to
On Fri, 28 Sep 2007 23:08:08 -0400, Eric Sosman wrote:

> Kenneth Brody wrote:
>> [...]
>> [1] We would get "bug reports" on things like "isleap() says that
>> the year 2000 is a leap year", [...]
>
> The response to that one was a classic. It circulated
> widely on the Net even before there was a Web, and can still
> be found: Google "11-60903".

It suggests that leap seconds are due to the small inaccuracy of
the Gregorian calendar, whereas in fact they are due to the fact
that the Earth's rotation is slowing down. The proposed correction
to Gregorian calendar is to make years multiple of 4000 non-leap
(though actually the Gregorian calendar falls by about one day
in 8000 years, so accepting that proposal only for multiples of
8000 would make more sense; but anyway, the increment of the
duration of the day (the one for which leap seconds are for) will
cause the duration of the year measured in days to decrease, and
the precise rate of that is unpredictable (for example, in the
early 2000s Earth's rotation sped up, so in those years we didn't
have any leap seconds for 7 years) and therefore deciding now
changes which will apply 1993 or 5993 years from now is pointless).

--
Army1987 (Replace "NOSPAM" with "email")
A hamburger is better than nothing.
Nothing is better than eternal happiness.
Therefore, a hamburger is better than eternal happiness.

Keith Thompson

unread,
Sep 30, 2007, 2:06:15 PM9/30/07
to
"Charlie Gordon" <ne...@chqrlie.org> writes:
> "Keith Thompson" <ks...@mib.org> a écrit dans le message de news:
> lnd4w1k...@nuthaus.mib.org...
[...]

>> Does MS really define a type LONG, distinct from long, or did you put
>> LONG in all-caps for emphasis?
>
> As was already mentioned elsethread, MS typedefs a truckload of all caps
> types such as BYTE, WORD, LONG and DWORD intrinsically hard-wired for widths
> of 8, 16 and 32 bits. After 20 years of brainwashing, it was impossible to
> change the width of LONG or long for the WIN64 architecture.
[...]

But long and LONG are the same size, right? Right???

Mark McIntyre

unread,
Sep 30, 2007, 6:42:32 PM9/30/07
to
On Sun, 30 Sep 2007 11:06:15 -0700, in comp.lang.c , Keith Thompson
<ks...@mib.org> wrote:

>
>But long and LONG are the same size, right? Right???

You would think so, wouldn't you?

Kenneth Brody

unread,
Sep 30, 2007, 4:12:06 PM9/30/07
to
Eric Sosman wrote:
>
> Kenneth Brody wrote:
> > [...]
> > [1] We would get "bug reports" on things like "isleap() says that
> > the year 2000 is a leap year", [...]
>
> The response to that one was a classic. It circulated
> widely on the Net even before there was a Web, and can still
> be found: Google "11-60903".

I've seen that before, many years ago.

However, our response at the time was basically "Not a bug -- the
year 2000 _is_ a leap year."

I also found a link to the actual text of the Act which changed the
British empire (including the U.S.A-to-be) to the Gregorian calendar.
I don't recall which URL it was at that time, but here is one that
works today:

http://webexhibits.org/calendars/year-text-British.html

John J. Smith

unread,
Sep 30, 2007, 8:45:03 PM9/30/07
to
jacob navia wrote:

Well if nothing else, it would definitely help discover portability
issues since plain int and long (and pointers thereto) are not
necessarily the same size and/or representation. I also think the
parent article to my response was wondering whether signed and
unsigned quantities should be treated differently.

context was

>>> long l;
>>> unsigned long ul;
>>>

>>> int *pi = &l; /* line 12: produces diagnostic */
>>> unsigned int *pui = &ul; /* line 13: no diagnostic */

>>> printf(" l * 10: %li\n", l * 10); /* printf argument mismatch...*/
>>> printf(" ul * 10: %lu\n", ul * 10); /* no warning */


I can confirm that lcc-win32 (version 3.8) issues a warning for
the statement marked 'line 12:' but not for the statement marked
'line 13:'. (MSVC warns in both cases)

Is lcc-win32's behaviour really intentional?


--
John J. Smith
(still curious)

It is loading more messages.
0 new messages