main() in C90

C

CBFalconer

Hans said:
.... snip ...

That's what I thought always, but I'm not anymore so sure.
According to a recent thread...

* H. Schildt (book writer and ISOC member)
- writes that you are free to use void main()
* Richard Heathfield (book writer)
- says that void main() is false
* Chris Hills (ISOC member)
- says that void main() is valid C
* Jack Klein (writer of C library and inventor of Klein Bottle)
- says that void main() is not valid C code

I am still very confused.

Then resolve it. Read the standard. Try the following links:

Some useful references about C:
<http://c-faq.com/> (C-faq)
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf> (C99)
<http://cbfalconer.home.att.net/download/n869_txt.bz2> (C99, txt)

Hint - RH and JK are accurate. HS is notorious.
 
R

Randy Howard

Billy said:
Hi, in C90 is "int main()" valid, the same as "int main(void)" and "int
main(int argc, char *argv[])"?


AFAIK in C99 only "int main(void)" and "int main(int argc, char *argv[])
- and the **argv syntax" are the only valid ones.

In reality, "void main()" is also valid.

That's what I thought always, but I'm not anymore so sure. According to
a recent thread...

* H. Schildt (book writer and ISOC member)
- writes that you are free to use void main()
* Richard Heathfield (book writer)
- says that void main() is false
* Chris Hills (ISOC member)
- says that void main() is valid C
* Jack Klein (writer of C library and inventor of Klein Bottle)
- says that void main() is not valid C code

I am still very confused.

Apparently you are. The Klein surface, later known as a Klein bottle
was by Felix Klein in the late 1800s, you seem to be way off target on
at least some of it. ;-)
 
K

Keith Thompson

CBFalconer said:
Keith Thompson wrote: [...]
Not quite. The format string, again, is

"%.3s %.3s%3d %.2d:%.2d:%.2d %d\n"

Any of the "%...d" specifiers could result in an arbitrarily long
string (up to the width of INT_MIN) given a sufficiently large
argument. The "%3d" and "%.2d" specifiers, unlike "%.3s", don't
truncate their arguments.

No. The input is specified as a struct tm*, and that struct is
specified as having restricted value sizes. I believe they never
exceed 60, and are never negative. Some are 3 char. strings. That
struct is, in turn, created by provided code that interfaces with
some system specific timer.

The members of an object of type struct tm are of type int, and can
have any values in the range INT_MIN .. INT_MAX. C99 7.23.1.4, which
defines struct tm, says (emphasis added):

The semantics of the members and their *normal* ranges are
expressed in the comments.

The gmtime() and localtime() functions should always generate struct
tm values with members having values in the "normal" ranges, but
there's nothing to prevent user code from storing any arbitrary values
in any of the members. In other words, the given ranges are
constraints on the results of gmtime() and localtime(), not on the
type. (There's no way in the language to specify or enforce such a
constraint.) Indeed, the mktime() function is specifically designed
to work with values outside the normal ranges.

Consider this program:

#include <stdio.h>
#include <time.h>
int main(void)
{
struct tm tm;
tm.tm_sec = 999;
tm.tm_min = -99;
tm.tm_hour = 0;
tm.tm_mday = 0;
tm.tm_mon = 0;
tm.tm_year = -1801; /* year 99 */
tm.tm_wday = 0;
fputs(asctime(&tm), stdout);
return 0;
}

I believe it is completely portable (to conforming hosted
implementations), and must produce the following output (barring
output errors):

Sun Jan 0 00:-99:999 99
 
K

Keith Thompson

Richard Heathfield said:
CBFalconer said:

The "as if" rule applies. Since a strictly conforming program can't tell
whether a larger buffer is allocated, it's okay to allocate a larger
buffer.

I agree, but I'm going to quibble about terminology.

The body of the standard doesn't mention the "as if" rule, but the
index has an entry that points to C99 5.1.2.3; I'm not sure that
anything in that section directly applies to this. For that matter,
I'm not sure just what part of that section is supposed to define the
"as-if" rule.

It's true that a strictly conforming program can't tell the
difference, but that's not sufficient. If a program with unspecified
behavior could tell the difference, then an implementation wouldn't be
allowed to use a larger buffer. But in fact any program that avoids
undefined behavior can't tell the difference, and that's why a larger
buffer is allowed.

Consider an implementation that provides an asctime() function
identical to the one presented in the standard, except that
static char result[26];
is replaced by
static char result[100];
Only a program that invokes undefined behavior (by overflowing a
26-byte buffer) would behave differently in the two cases.

For that matter, the implementation of asctime() could declare a
26-byte buffer, but the compiler could recognize this as a special
case and arrange for extra memory to reserved immediately after the
result buffer.
 
K

Keith Thompson

Hans Schneider said:
Billy said:
Hi, in C90 is "int main()" valid, the same as "int main(void)" and "int
main(int argc, char *argv[])"?

AFAIK in C99 only "int main(void)" and "int main(int argc, char *argv[])
- and the **argv syntax" are the only valid ones.

In reality, "void main()" is also valid.

That's what I thought always, but I'm not anymore so sure. According to
a recent thread...

* H. Schildt (book writer and ISOC member)
- writes that you are free to use void main()
* Richard Heathfield (book writer)
- says that void main() is false
* Chris Hills (ISOC member)
- says that void main() is valid C
* Jack Klein (writer of C library and inventor of Klein Bottle)
- says that void main() is not valid C code
[...]

Herbert Schildt is notorious for his dangerously incorrect books.
See, for example, <http://www.lysator.liu.se/c/schildt.html> and
<http://www.seebs.net/c/c_tcr.html>.

Here's the truth.

There are two kinds of conforming C implementations, hosted and
freestanding. You're not likely to run into a freestanding
implementation unless you work on embedded systems (though it's been
argued that some MS Windows C implementations are really
freestanding).

For a hosted implementation, the main function may have this form:
int main(void) { /* ... */ }
or this form:
int main(int argc, char *argv[]) { /* ... */ }
or equivalent. The "or equivalent" allows for things like using a
typedef for int rather than int, or using "char **argv" rather than
"char *argv[]", or using different names for argc and argv.

If you define main in any other way, such as
void main(void) { /* ... */ }
then the behavior of your program is undefined. It's not "illegal",
in the sense that the compiler isn't required to complain, but it's
not required to work, and the compiler *could* reject it outright.

*Except that*, in both C90 and C99, implementations are permitted to
provide extensions, as long as they don't break anything. (That's a
somewhat imprecise summary; see the standard for the exact wording.)
Such extensions must be documented. So if your compiler's
documentation says that "void main(void)" is allowed, and specifies
what it does, then a program that uses "void main(void)" has well
defined behavior *for that implementation*. But if you try to compile
and run that some program on another implementation, it might fail to
work, in ways ranging from being rejected outright by the compiler to
misbehaving in subtle ways during execution.

If you write "int main(void)", you *know* that it will work under any
conforming hosted implementation. Writing "void main(void)" gains you
absolutely nothing; it just makes your program less portable.
Remember that those implementations that allow "void main(void)" are
still required to support "int main(void)".

To summarize, "void main(void)" isn't actually illegal, but it may or
may not work; "int main(void)" will always work. (The rules are
different for freestanding implementations.)
 
H

Harald van Dijk

The body of the standard doesn't mention the "as if" rule, but the index
has an entry that points to C99 5.1.2.3; I'm not sure that anything in
that section directly applies to this. For that matter, I'm not sure
just what part of that section is supposed to define the "as-if" rule.

That's likely p5:
"The least requirements on a conforming implementation are:
-- At sequence points, volatile objects are stable in the sense that
previous accesses are complete and subsequent accesses have not yet
occurred.
-- At program termination, all data written into files shall be
identical to the result that execution of the program according to
the abstract semantics would have produced.
-- The input and output dynamics of interactive devices shall take place
as specified in 7.19.3. The intent of these requirements is that
unbuffered or line-buffered output appear as soon as possible, to
ensure that prompting messages actually appear prior to a program
waiting for input."

An implementation that defines a larger buffer size for use by asctime
can still meet these requirements.
 
C

Chris Hills

CBFalconer said:
Below is the appropriate section of the standard, copied from
N869.txt.

N869.txt is NOT a standard

Undefined behaviour cut..........

You can't have it both ways. .
 
C

Chris Hills

Is he an ISO -c member?
But his books are known to be full of holes. On the other hand when did
he write it? C has been evolving for about 35 years.

In a self hosted system.

On a hosted system
Hint - RH and JK are accurate.

They are very accurate pedants who as has been decided elsewhere are
often accurate but very unhelpful, almost misleading, at the same time.
 
K

Keith Thompson

Chris Hills said:
Is he an ISO -c member?

I think he's claimed to be an "observing member" or something like
that. I've heard that actual members of the committee don't recall
seeing him at any meetings.
But his books are known to be full of holes. On the other hand when
did he write it? C has been evolving for about 35 years.

Schildt has used "void main()" in examples long after he should have
known better. He's even used it in his annotations in "The Annotated
ANSI C Standard".
In a self hosted system.

Quibble: the term used by the standard is "freestanding
implementation". (The term "self hosted", in my experience, refers to
using a compiler to compile itself.)
On a hosted system


They are very accurate pedants who as has been decided elsewhere are
often accurate but very unhelpful, almost misleading, at the same
time.

"as has been decided elsewhere". Interesting use of the passive
voice. If this is your opinion, please just say so. (For the record,
I disagree.)
 
J

jacob navia

Keith said:
(The workaround is easy enough: be careful when using asctime(), or
use strftim() instead.)

Of course the workaround is easy, and lcc-win will never
overflow the buffer.

BUT tell me, why do we have to program workarounds for the standard?

What kind of standard is this one that needs workarounds for its BUGS?
 
H

Harald van Dijk

N869.txt is NOT a standard

The section (7.23.3.1) is identical between n869 and the standard, so
while n869 is indeed not the standard, the claim that the text was (also)
the appropriate section of the standard was correct.
 
R

Richard Tobin

What kind of standard is this one that needs workarounds for its BUGS?

As someone who's been on several standards committees, I think you'll
find it's the normal kind.

-- Richard
 
I

Ioannis Vranos

Keith said:
Schildt has used "void main()" in examples long after he should have
known better. He's even used it in his annotations in "The Annotated
ANSI C Standard".


Not to mention M$ who does this in its MSDN documentation too, since
long time ago.
 
R

Randy Howard

Not to mention M$ who does this in its MSDN documentation too, since
long time ago.

Their compiler supports it as an extension, so it's appropriate for
them to do so, although it would be nice if they bothered to tell the
reader that using it would break the IF ERRORLEVEL processing supported
by their batch file system.
 
H

Harald van Dijk

Not to mention M$ who does this in its MSDN documentation too, since
long time ago.

Interestingly, Microsoft (its sixth letter is an 's', by the way) uses
void main() in its documentation for implementation-defined extensions,
without explicitly defining void main() as an alternate allowed form. I
wonder if that by itself is enough to consider it an implementation-
defined allowable form. The current documentation uses int main(void), so
it probably wasn't intended.
 
B

Ben Bacarisse

Chris Hills said:
N869.txt is NOT a standard

Undefined behaviour cut..........

You can't have it both ways. .

Nether can you. You are on record as objecting to pedantic postings
that are correct but unhelpful. If there a difference between the
cited text and the published standard? If so, telling us would be
very helpful. If not, knowing that would help too.
 
J

James Kuyper

CBFalconer wrote:
....
No. The input is specified as a struct tm*, and that struct is
specified as having restricted value sizes.

It's values are documented as having a normal range. It's values are
explicitly allowed to be outside that range before a call to mktime(),
and are guaranteed to be within that range after the call. The other
functions that take struct tm arguments do not specify whether or not
the values are required to be in their normal ranges.
 
J

James Kuyper

CBFalconer wrote:
....
The specification says:

"using the equivalent of the following algorithm."

and the following algorithm specifies a static buffer size of 26.
This leaves no option, IMO. It does allow implementation in
assembly code, or in Druidism, as pleases the implementor.

In what way does the behavior of an implementation of asctime() fail to
be equivalent to that algorithm, when the behavior of that algorithm is
defined, if the implementation uses an overlong buffer?
 
J

James Kuyper

Hans Schneider wrote:
....
* H. Schildt (book writer and ISOC member)
- writes that you are free to use void main()
* Richard Heathfield (book writer)
- says that void main() is false
* Chris Hills (ISOC member)
- says that void main() is valid C
* Jack Klein (writer of C library and inventor of Klein Bottle)
- says that void main() is not valid C code

I am still very confused.

You might try looking at the standard itself. None of the other sources
you've mentioned are authoritative.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,250
Latest member
Charlesreero

Latest Threads

Top