If void main is illegal, WHY is it so common in RKM?
whatever some people might say, the Amiga OS is unlikely to be written
by people who know C that poorly
The Amiga OS was written before ANSI C. I have the first edition
here of the RKM (1986), and it always says:
main()
This was probably before the keyword `void' was even introduced
to Amiga C compilers.
There are other non-standard features about the Amiga. My
favourite one was that you could determine if your program
had been started up from the CLI or from a Workbench icon
by declaring:
main(argc, argv)
int argc;
char **argv;
{
if(argc==0) {
/* Workbench stuff */
} else {
/* CLI stuff */
}
...
}
--
Miguel Carrasquer ____________________ ~~~
Amsterdam [ ||]~
m...@inter.NL.net ce .sig n'est pas une .cig
[ Please keep your lines shorter than 75 characters ]
>It's not illigal. It's just "neater" to have a programm return true,
>or false, or whatever the OS defines as successful programm
>termination.
It *is* illegal, the law (ANSI/ISO C standard) says so.
Casper
A simple main() is and always has been OK. Before the `void'
keyword, there was no other way to declare a "void" function
but to declare it as (implied) int, and exit it with a
return; or a }. The examples in the RKM don't explicitly
return a value from main(), so when `void' was introduced
in some compilers, they changed the declarations of all
functions that were implicitly void. This is OK for any other
function but `main'. All this means is that this too was
done before the ANSI standard, that it was not corrected
when the standard appeared, and that it's probably safe
*on an Amiga* to declare main() as void. But why should you?
But a simple main() isn't particularly nonstandard. I believe
that a function whose type is undeclared is of type int. Could
a C lawyer out there check up on this?
-- Bill Evans
It's not illigal. It's just "neater" to have a programm return true, or false, or whatever the OS defines as successful programm termination. If you set main up to return type 'VOID', then any return value will be given through a call to 'exit()', as opposed to just using 'return()' to return your value. It's just one of those funny things that no standard was ever defined for. Unless your OS /absouletely/ needs a return value, most of the time it doesn't matter if you give one or not.
And I wouldn't put money on how well all the programmers that worked on Amiga OS knew C. ;)
//
// Justin McKinnerney
// IDT / IIA Director of Software Engineering
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// INET: jus...@gangrel.ios.com CIS: 74262,3173 AT&T: (201)928-1000x149
//
: Er...
The Amiga OS wasn't even written in C, at least not originally. It was
originally written in BCPL, which I'm told is a sort of progenitor of C.
Knowing how totally uncivilized C was when AmidaDOS was originally
written, I shudder to think what BCPL was like.
--
* N E W I M P R O O V E D . S I G *
w i t h
* W E D N E S D A Y S P A C I N G * ( t m )
------------------------------------------------------------------------------
T h e a g g r e g a t e i n t e l l i g e n c e o n t h i s
p l a n e t i s a c o n s t a n t . T h e p o p u l a t i o n ,
h o w e v e r , i s g r o w i n g .
------------------------------------------------------------------------------
"O K , s o h e ' s n o t t e r r i b l y f e a r s o m .
B u t h e c e r t a i n l y c a u g h t u s b y
s u r p r i s e !"
------------------------------------------------------------------------------
>It's not illigal. It's just "neater" to have a programm return true, or false,
> or whatever the OS defines as successful programm termination. If you set main
> up to return type 'VOID', then any return value will be given through a call
> to 'exit()', as opposed to just using 'return()' to return your value.
If you had followed the newsgroup for any period or read the FAQ you would
not have posted this.
According to the standard the only recognised return type for main is int -
anything else results in *undefined behaviour* i.e. it ceases to make
any guarantees whatsoever about what your program will do. From a practical
viewpoint a compiler is allowed to use a different stack frame for an
int function to a void function so its entirely possible (and legal) that
when the C startup code (which may be fixed library code that expects to
call an int function) will crash before your code ever starts to run.
> It's
> just one of those funny things that no standard was ever defined for. Unless
> your OS /absouletely/ needs a return value, most of the time it doesn't matter
> if you give one or not.
The standard is clear enough - main must return int. However the implementation
may then proceed to do whatever it likes with the return value, including
discarding it. The reason it is done this way is that code you write on,
say, the Amiga remains portable and will still compile and run on other
systems which do require a return value. To help with this the standard
also defines the intent of the return values EXIT_SUCCESS, EXIT_FAILURE and 0.
--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------
In article <77871780...@mclink.it>, Adam Atkinson writes:
> flicking through the libraries volume of the Amiga Rom Kernel Manuals
> I can't help noticing that VOID main is all over the place.
> If void main is illegal, WHY is it so common in RKM?
As the title "*Amiga* ROM Kernel Manuals" implies, all examples
contained therein are highly Amiga-specific. The discussion why miximg
up the return type may endanger the integrity of the stack frame does
not apply to Amigas (at least as long as structures are not involved),
and it is a "common extension" for Amiga C compilers to special-case a
main() returning void to mean a return value of 0. (Unfortunately DICE
is exempt from this.)
However, The Correct Amiga Way to define main() is of course:
LONG main(int argc, UBYTE **argv)
F'up-To: comp.sys.amiga.programmer
-- __
__/// Arno Eigenwillig <ar...@yaps.dinoco.de> \\ Stamp out patents
\XX/ MIME & any PGP V2 supported * V:+49-2225-5870 \\ for algorithms!
Don't trust hearsay! Read the reference! [Terry Ritter]
In article <34dihr$c...@nermal.cs.uoguelph.ca>, David L Evens writes:
> The Amiga OS wasn't even written in C, at least not originally. It was
> originally written in BCPL, which I'm told is a sort of progenitor of C.
Please do not spread discrediting misinformation about the AmigaOS.
[0.5 :-)]
The AmigaOS is not monolithic. Its kernel and low-level routines have
originally been written in assembly, the rest has been written in C.
The only exception to this is the DOS, which is an adaption of
Metacomco's Tripos and has thus been written in BCPL. As of OS Rele-
ase 2, C replaced BCPL nearly completely.
> Knowing how totally uncivilized C was when AmidaDOS was originally
> written, I shudder to think what BCPL was like.
The worst thing about BCPL is that it left two nasty marks on the
AmigaOS: The BPTR (BCPL pointer) which is a real pointer divided by
four, which leads to unreasonable alignment requirements, and the BSTR
which is a BPTR to an array of bytes with the length in the first
byte, as opposed to the otherwise global adoption of C strings in the
Amiga OS.
F'up-To: comp.sys.amiga.programmer
-- __
__/// Arno Eigenwillig <ar...@yaps.dinoco.de> \\ Stamp out patents
\XX/ MIME & any PGP V2 supported * V:+49-2225-5870 \\ for algorithms!
Those were the days, when sex was dirty
and the air was clean! [Conny Koenig]
>ANSI/ISO C standard is /not/ the law. Whatever compiler you are using is.
>If the compiler you're using doesn't support any ANSI/ISO standard,
>then I promice, you won't be coding ANSI/ISO standard.
The ANSI standard isn't the law - it's just a good idea.
-jim
>The Amiga OS wasn't even written in C, at least not originally. It was
>originally written in BCPL, which I'm told is a sort of progenitor of C.
>Knowing how totally uncivilized C was when AmidaDOS was originally
>written, I shudder to think what BCPL was like.
BCPL was (is) a great language. At the time C was an evolving not particularly
well established language whereas BCPL had its wrinkes ironed out many
years previously!
Ahem.
After posting this, I got email from someone whose who suggested
that I read the FAQ more carefully. I replied to his mail with a cc
to P. J. Plauger, who replied that the intent of the Standard is
to permit only the two declarations for main shown in the Standard
itself, ie.:
int main(void)
int main(int, char **)
Mr. Plauger pointed out that other declarations may work
on some systems, but won't be portable.
I'm sorry if I confused the issue with my earlier, ill-considered post.
--
"Obviously unlike you people, I don't have time to edit the newsgroups line
for every single article I post." -- ma...@cs.yale.edu
>jus...@gangrel.lupine.org (Justin McKinnerney) writes:
>>It's not illigal. It's just "neater" to have a programm return true,
>>or false, or whatever the OS defines as successful programm
>>termination.
>It *is* illegal, the law (ANSI/ISO C standard) says so.
>
I keep reading this here, but all I see in the standard itself is
that if main() returns without a value, the termination status
returned to the OS is undefined.
Note that it's not the behavior of the program that's undefined,
but the value(if any) that is passed back to the OS.
Undefined != illegal
Having said that, I still agree with the general consensus here that
void main() is a very bad idea, since it has potential to barf on
some OSes.
In another part of the standard (6.1.2.6, second paragraph) says:
All declarations that refer to the same object or function shall have
compatible type; otherwise the behavior is undefined.
(the return type and parameter types are significant when determining
if two function prototypes are compatible).
main has two types: (we've already been through this)
int main(void);
int main(int, char **);
a compiler is allowed to add meaning to other types of main, most
commonly, a third parameter of type 'char **'.
Last time I checked, 'void' and 'int' are not compatible types, and
for those who don't remember, main() is called from the startup code,
which expects it to return an int.
--
Zach Heilig (hei...@aero.und.nodak.edu)
>ANSI/ISO C standard is /not/ the law. Whatever compiler you are using is. If the compiler you're using doesn't support any ANSI/ISO standard, then I promice, you won't be coding ANSI/ISO standard.
According to this line of reasoning, we'd better throw the standard away
and replace it with the vendor supplied manuals, because they define the
law. And, of course, split this newsgroup in a zillion of groups, one
for each compiler.
Could you, please, learn how to use the RETURN key? There is no
requirement that a full paragraph has to be written on a single line.
Dan
--
Dan Pop
CERN, CN Division
Email: dan...@cernapo.cern.ch
Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland
ANSI/ISO C standard is /not/ the law. Whatever compiler you are using is. If the compiler you're using doesn't support any ANSI/ISO standard, then I promice, you won't be coding ANSI/ISO standard.
Heh, politics in programming. Give me a friggin' break!
There is a peculiarity in AMIGA C. There are a whole bunch of standard
#defines and typedefs in the header files. One of these is
#define VOID int
(others are BOOL, USHORT, APTR, et al)
This permits them to make declarations like:
VOID main()
This particular convention was fairly common in the latter days of K&R 'C',
but, once the preprocessor handles it, the declaration still comes out as
int main()
and were therefore OK. Then the ansi standard declared that void
was a keyword, and PING. Immediately there are all kinds of compiler
dependencies. When in doubt, try this in a header file:
#ifndef VOID
#define VOID int
#endif
#ifndef void
#define void VOID
#endif
Dave
Question #1: Does that mean, that the compiler has a predefined prototype
of int main( whatewer ) ? Or, I still can declare main() as
any other function, and the linker will scream that signatures
in the startup and in my code do not match ?
Question #2: Why is it forced to declare main as int if this is a restriction
of the certain OS-es and not the language ? It was very nice in
K&R1 that the language DIDN'T depend on the OS. It made
it so universal.
Question #3: Same issue, the standard header files/libraries contain quite
a lot of very much OS dependent stuff, or rather, assume,
that there's an OS around the program. It isn't always the case,
would that mean that no compiler specifically written for em-
bedded systems will ever be ANSI compliant, because of the
lack of library routines which are meaningless in such an
environment ? That is, I can't program my curtain opener micro
in ANSI C ?! Not to mention my super new OS's booter, which is
called by the reset vector, so no prototypes would be matched,
no startup code exists, nor any libraries, since the OS is just
going to be booted.
So, why does a system-independent language standard encorporate OS concepts ?
Zoltan
--
Zoltan Kocsi <zol...@research.canon.oz.au>
Zoltan, the standard says, and I quote...
5.1.2.1 Freestanding Environment
In a freestanding environment (in which C program execution may take place
without any benefit of an operating system), the name and type of the function
called at program startup are implementation-defined. There are otherwise no
reserved identifiers. Any library facilities available to a freestanding
program are implementation defined.
The effect of program termination in a freestanding environment is
implemented-defined.
Okay? It is possible to use ISO C to write curtain rod controllers.
Now in a hosted environment things differ, the ISO C standard requires
that a conforming program return an int from main() (if it ever returns
but I'll leave the general solution of that problem as an exercise for
the reader ;-). The hosted environment's startup code is then responsible
for mapping the int to whatever the OS wants (an int as in UNIX or send
a success message or whatever, not my problem).
--
Andy Newman (an...@research.canon.oz.au) (Not a Canon spokesperson)
>
>Question #2: Why is it forced to declare main as int if this is a restriction
> of the certain OS-es and not the language ? It was very nice in
> K&R1 that the language DIDN'T depend on the OS. It made
> it so universal.
>
Is it that difficult to read the FAQ before posting nonsense? The return
type of main has absolutely nothing to do with the underlying OS, because
main doesn't return to the OS, it returns to a routine in the startup
code. And that routine expects main to return an int and it may be upset
if main doesn't. I can't see any OS dependency here.
Here is the quote from the FAQ, hoping that it will help reduce the
number of silly arguments posted in this thread:
5.12: Can I declare main as void, to shut off these annoying "main
returns no value" messages? (I'm calling exit(), so main
doesn't return.)
A: No. main must be declared as returning an int, and as taking
either zero or two arguments (of the appropriate type). If
you're calling exit() but still getting warnings, you'll have to
insert a redundant return statement (or use some kind of
"notreached" directive, if available).
Declaring a function as void does not merely silence warnings;
it may also result in a different function call/return sequence,
incompatible with what the caller (in main's case, the C run-
time startup code) expects.
References: ANSI Sec. 2.1.2.2.1 pp. 7-8.
>In <34igac$l...@ankh.iia.org> jus...@gangrel.lupine.org (Justin McKinnerney)
> writes:
.
.
>>ANSI/ISO C standard is /not/ the law. Whatever compiler you are using is. If
> the compiler you're using doesn't support any ANSI/ISO standard, then I
> promice, you won't be coding ANSI/ISO standard.
It's meaningless to discuss what is and isn't legal without some law/standard
framework to refer to. In comp.lang.c that happens to be the ANSI/ISO C
standard by convention unless explicitly stated otherwise.
>Could you, please, learn how to use the RETURN key? There is no
>requirement that a full paragraph has to be written on a single line.
Maybe it's the law/standard in Justin's locality! :-)
>I keep reading this here, but all I see in the standard itself is
>that if main() returns without a value, the termination status
>returned to the OS is undefined.
You mean ANSI/ISO 5.1.2.2.3? That's referring to when you return without
a value or fall off the end of a main function defined as returning *int*.
You'll see from 5.1.2.2.1 main functions that return void are simply
undefined.
>Note that it's not the behavior of the program that's undefined,
>but the value(if any) that is passed back to the OS.
In the case of int main that doesn't return a value, yes, in the case of
main defined as something other than int, no.
>Undefined != illegal
'Illegal' isn't a word that's well defined in the context of the C standard.
It's not unreasonable to equate illegal with undefined behaviour. The only
thing to note about void main is that it does not require a diagnostic from
the compiler.
[ me, basically stating that two different prototypes for the same
function name (in two source files) don't have to link up correctly ]
>Question #1: Does that mean, that the compiler has a predefined prototype
> of int main( whatewer ) ? Or, I still can declare main() as
> any other function, and the linker will scream that signatures
> in the startup and in my code do not match ?
(the standard says that the compiler can't supply a prototype for
'main()')
Most likely the linker would scream. I've come up with a valid system
for naming external identifiers that would break 'void main()' or any
other mis-matched return types (the basics are simply to add the
return type to the external identifier). The reason I came up with it
wasn't to make 'void main()' (or struct foo main()) not work, but to
catch instances where someone forgot to include a header (like
<math.h>) for a function that returns other than int. Under my
implementation, the linker would say something like:
un-resolved external reference 'int main()' in object /lib/startup.o
un-resolved external reference 'int sin()' in object ./someprog.o
if you mis-declared main() and forgot to include <math.h>. (just for
example... I haven't actually started this project yet...)
>Question #2: Why is it forced to declare main as int if this is a restriction
> of the certain OS-es and not the language ? It was very nice in
> K&R1 that the language DIDN'T depend on the OS. It made
> it so universal.
Compilers are allowed to accept more than the two defined prototypes
for main(), but the programmer has to keep in mind that anything else
doesn't have to be portable.
>Question #3: Same issue, the standard header files/libraries contain quite
^^^^^^^^^^^^
reminder: headers don't have to be files.
> a lot of very much OS dependent stuff, or rather, assume,
> that there's an OS around the program. It isn't always the case,
> would that mean that no compiler specifically written for em-
> bedded systems will ever be ANSI compliant, because of the
> lack of library routines which are meaningless in such an
> environment ? That is, I can't program my curtain opener micro
> in ANSI C ?! Not to mention my super new OS's booter, which is
> called by the reset vector, so no prototypes would be matched,
> no startup code exists, nor any libraries, since the OS is just
> going to be booted.
ANSI defines two different environments, one with an OS (hosted), and
one without an OS around it (freestanding). What most people use and
talk about is the hosted environment. The freestanding requirements
don't include having a standard library (only 4 standard headers, no
externally defined references, not even 'main()').
>So, why does a system-independent language standard encorporate OS concepts ?
It supplies a complete standard, and a minimal one, depending on what
environment you are compiling under. The library has to have some
concept of an OS (a very minimal one that is) otherwise we can't write
generally usable programs with the standard library.
--
Zach Heilig (hei...@aero.und.nodak.edu)
--
Zach Heilig (hei...@aero.und.nodak.edu)
Are you saying you have implemented `name mangling' in C?
I'm curious about how you've done it...
>dependencies. When in doubt, try this in a header file:
>#ifndef VOID
>#define VOID int
>#endif
>#ifndef void
^^^^
>#define void VOID
>#endif
This won't work. void will not be defined on a standard ANSI system that
recognises the void keyword.
--
Ron House. USQ
(ho...@usq.edu.au) Toowoomba, Australia.
>wri...@rpm2.aes.mb.doe.ca (David Wright) writes:
>>#ifndef void
> ^^^^
>>#define void VOID
>>#endif
>This won't work. void will not be defined on a standard ANSI system that
>recognises the void keyword.
It will work. Macro expansion happens before keywords are recognized.
It still isn't a good idea. Think about what this does to
int main (void) { .... }
hp
--
_ | h...@vmars.tuwien.ac.at | Peter Holzer | TU Vienna | CS/Real-Time Systems
|_|_) |------------------------------------------------------------------------
| | | It's not what we don't know that gets us into trouble, it's
__/ | what we know that ain't so. -- Will Rogers
#ifndef void will *always* be true, whether the compiler recognizes
the `void' keyword or not, so, yes, it will work, too well. `void'
simply isn't a preprocessor symbol.
My guess is that this is really done like this:
#ifdef SOME_ANSI_COMPILER
#define VOID void
#endif
#ifdef SOME_K_AND_R_COMPILER
#define VOID
#endif
I wouldn't count on it. There is no predefined prototype for
main(), because the ANSI/ISO C Standard says there mustn't be,
presumably because it's impossible in C to declare a function-
returning-int-but-accepting-either-zero-or-two-fixed-arguments.
(Note that any declaration involving ... describes a function
accepting a varying number of arguments, which main does not.)
A compiler may have to treat main() specially in order to handle
its schizophrenic declaration, and a compiler may be able to warn
you if you screw it up, but the warning won't be because of a
prototype.
I wouldn't trust a linker to complain either. All too few
linkers attempt to check any aspects of "function signatures" at
all, and even those that do might have problems performing their
checks in the face of main's schizophrenia.
> Question #2: Why is it forced to declare main as int if this is a restriction
> of the certain OS-es and not the language ? It was very nice in
> K&R1 that the language DIDN'T depend on the OS. It made
> it so universal.
Some operating systems define a 32-bit exit status for processes.
Some use 16 bit status codes; some use 8; some don't have a
concept of exit status at all. Therefore, if main() *were*
system-dependent, we would have to declare it as int, or long, or
short, or unsigned char, or void, depending on the operating
system we were compiling for today. Fortunately, main is *not*
system-dependent. It is always%% declared as returning int, and
it's the job of the system-specific run-time startup code to do
something appropriate with the int which main() returns.
-----------------------------------------------------------------
%% [footnote] main() is always declared as returning int in
correct programs. It is all too frequently declared as returning
void in PC-addled programs and books.
> Question #3: Same issue, the standard header files/libraries contain quite
> a lot of very much OS dependent stuff, or rather, assume,
> that there's an OS around the program.
Yes, but the assumptions about that OS are very (and often
cripplingly) minimal, and the interfaces to the various OS
routines are carefully defined to be system-independent.
(For example, getc() returns \n from text files regardless
of the underlying system's line delineation conventions.)
> It isn't always the case,
> would that mean that no compiler specifically written for em-
> bedded systems will ever be ANSI compliant, because of the
> lack of library routines which are meaningless in such an
> environment ? That is, I can't program my curtain opener micro
> in ANSI C ?! Not to mention my super new OS's booter, which is
> called by the reset vector, so no prototypes would be matched,
> no startup code exists, nor any libraries, since the OS is just
> going to be booted.
ANSI C defines freestanding environments for exactly this reason.
Freestanding environments don't have anything special about
main() (they might use any entry point, with any declared return
type), and there are no defined library facilities, for OS
interfacing or otherwise. Freestanding environments are
specifically intended to be used for things like toasters,
curtain openers, bootstrap loaders, and operating systems
themselves.
> So, why does a system-independent language standard encorporate OS concepts ?
Because certain OS concepts are vitally important to most
programs, and almost universally available in some form or
another. Many people wish that C incorporated more OS concepts,
thus the prevalence of "How do I read one character without
waiting for RETURN?" questions on comp.lang.c.
Steve Summit
s...@eskimo.com
In article <ZOLTAN.94...@radics.research.canon.oz.au>, Zoltan Kocsi writes:
> Question #1: Does that mean, that the compiler has a predefined prototype
> of int main( whatewer ) ?
No. This would kill the freedom to choose one of int main(void) and
int main(int, char **).
> Or, I still can declare main() as
> any other function, and the linker will scream that signatures
> in the startup and in my code do not match ?
Well, "most linkers are basically 1950s' designs" (B.S.) and will not
scream about that.
> Question #2: Why is it forced to declare main as int if this is a restriction
> of the certain OS-es and not the language ? It was very nice in
> K&R1 that the language DIDN'T depend on the OS. It made
> it so universal.
Why is it not supported by ANSI to call BltMaskBitMapRastPort()? After
all, it is a restriction in some OSs [1] that this function does not
exist, and not in the language.
#undef IRONY
Hey, tolerating void main(...) is a peculiarity of some systems.
Universality always comes from defining a "common denominator", and
void main(...) just is not contained in it (namely the ANSI/ISO C
standard).
_______
[1] namely in ~(AmigaOS)
-- __
__/// Arno Eigenwillig <ar...@yaps.dinoco.de> \\ Stamp out patents
\XX/ MIME & any PGP V2 supported * V:+49-2225-5870 \\ for algorithms!
"I AM NO PRINTER!" - "Strange printer, doesn't even have lower case."
[Stefan Scholl, Matthias Scheler]
Note, however, that the Amiga does* use the return value. It's not immediately
obvious, and I admit I don't like the shell syntax that does it, but the
return value is there. You can test for non-zero return of previous command
with "if warn". (Weird, no?)
>Lawrence Kirby | fr...@genesis.demon.co.uk
>Wilts, England | 7073...@compuserve.com
-seebs
--
Peter Seebach - se...@solutions.solon.com -- I need a job! Hire me!
GAT(CS/M/P/SS) d-- H++ s+: !g p? !au a- w+++ v+++/* C++++ UB/V++++ P+ L b+++ !D
3+(NetBSD/Amiga) E- N+++ K !W--- M++/-- V- -po+ Y+ t 5++ jx R G'''' tv- B---
e++ u** h--- f+ r+++ !n x+++* --SeebS-- / The Laughing Prophet
>Note, however, that the Amiga does* use the return value. It's not immediately
>obvious, and I admit I don't like the shell syntax that does it, but the
>return value is there. You can test for non-zero return of previous command
>with "if warn". (Weird, no?)
Oh well, yet one more nail on the coffin of void main(). Does anybody have a
stake to kill it off for good? :-)
--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------
> main(argc, argv)
> int argc;
> char **argv;
> {
> if(argc==0) {
> /* Workbench stuff */
> } else {
> /* CLI stuff */
> }
> ...
> }
In what way is that non-standard?
AFAIK, the standard does not promise that argc > 0,
nor that *argv points at anything in particular.
--
HansM
>
>AFAIK, the standard does not promise that argc > 0,
>nor that *argv points at anything in particular.
>
Well, it does promise that argv[argc] is a null pointer.
: However, The Correct Amiga Way to define main() is of course:
: LONG main(int argc, UBYTE **argv)
For a standard C compiler the correct way is:
int main(int argc, char **argv)
It is up to the compiler to do the right thing whether int is 16 or
32 bits etc.
--
Andrew Phillips (News/Sys Admin) and...@teslab.lab.oz.au +61 2 287 6551
--------------------------------
Just a SPOKE, not a SPOKESPERSON
: >dependencies. When in doubt, try this in a header file:
: >#ifndef VOID
: >#define VOID int
: >#endif
: >#ifndef void
: ^^^^
: >#define void VOID
: >#endif
: This won't work. void will not be defined on a standard ANSI system that
: recognises the void keyword.
Sorry, but this is wrong. Preprocessing directives and macro
invocations are done in translation phase 4. At this time, any keyword
is just an "identifier".
Andrew.
This stuff (AmigaOS) was written well before the ANSI
standard. I meant non-standard in the sense that
argc==0 cannot happen in unix (or any other system I
know of).
> Oh well, yet one more nail on the coffin of void main(). Does anybody have a
> stake to kill it off for good? :-)
If you find one, could you also put this topic out of its misery? 8-)
--
James Raynard
The statement in the following line is true.
The statement in the previous line is false.
>This stuff (AmigaOS) was written well before the ANSI
>standard. I meant non-standard in the sense that
>argc==0 cannot happen in unix (or any other system I
>know of).
argc = 0 can happen in Unix. Most programs don't like it though.
(xc is a program that execs a program w/o arguments)
truss -a -t execve xc vi
execve("/bin/vi", 0xEFFFF94C, 0xEFFFF950) argc = 0
argv:
Incurred fault #6, FLTBOUNDS %pc = 0xEF741158
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
Received signal #11, SIGSEGV [default]
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
*** process killed ***
Casper
Yeah if the program is exec'd by another program where it is the user's respon-
sibility to decide which arguments are passed, but never when the program is
begun by the OS. In that case argv[0] always contains the name of the program
and argc is at least equal to 1 if no additional arguments were passed.
This is the standard way things are done. I would only purposely exec a pro-
gram without argv[0] being the name of it if the program I was launching knew
of the deviation from the standard in the first place.
Jeff S. Dickson
jdic...@vtol.jpl.nasa.gov
Practically all programs in Unix are started by another program, most
of them by the shell (a normal program.) The only program that is
started by the OS is process 1, init, (and perhaps a page daemon and
swapper process.) This, however, has nothing to do with C.
--
Goran Larsson Phone: +46 13 155535 FAX: +46 13 160533
Approve AB +46 589 12810 +46 589 16901
h...@lorelei.approve.se ...!uunet!mail.swip.net!lorelei!hoh
By the pricking of my thumbs, something wicked this way comes
>ron house (ho...@helios.usq.EDU.AU) wrote:
>: wri...@rpm2.aes.mb.doe.ca (David Wright) writes:
>
>: >dependencies. When in doubt, try this in a header file:
>
>: >#ifndef VOID
>
>: >#define VOID int
>
>: >#endif
>
>: >#ifndef void
>: ^^^^
>: >#define void VOID
>
>: >#endif
>
>: This won't work. void will not be defined on a standard ANSI system that
>: recognises the void keyword.
>
>Sorry, but this is wrong. Preprocessing directives and macro
>invocations are done in translation phase 4. At this time, any keyword
>is just an "identifier".
...but not a macro definition which means that #ifndef void will succeed on
an ANSI system and if VOID is not previously defined void is substituted by
int breaking everything in sight. So, as Ron said, it won't work.
: Sorry, but this is wrong. Preprocessing directives and macro
: invocations are done in translation phase 4. At this time, any keyword
: is just an "identifier".
It may be that void looks like an identifier but it is not defined in
the sense that the above test expects - #define void something. The
test will fail whether the compiler uses the void keyword or not. Just
try on any ANSI compiler. I know that doesn't prove anything but it
would certainly be a good place to start thinking from.
--
D'Arcy J.M. Cain (da...@druid.com) |
Planix, Inc. | Democracy is three wolves and a
Toronto, Ontario, Canada | sheep voting on what's for dinner.
+1 416 424 2871 (DoD#0082) (eNTP) |
> flicking through the libraries volume of the Amiga Rom Kernel Manuals
> I can't help noticing that VOID main is all over the place.
> If void main is illegal, WHY is it so common in RKM?
Well, what I think we have here is just an unintentional patch that
was the result of the lack of a good standard. At the time that Amiga
OS was being written, only Lattice and Manx Aztec compilers were
readily available for easy port to 680X0 processors... The type VOID
was from a define of #define VOID int in some early compilers at the
time due to the "coming of age" for void, and ANSI's extreme
work on defining a standard.
void main IS illegal, and should be... If you ever cast
main void and dont pay attention to return values, you get a
"PROGRAM FAILED ERROR #776125366474" when it returns. Definately bad
news!!!
Also, dont forget all the other LOVELY Amiga standards for
the time: UBYTE, UWORD.. etc, etc... They did the best they could
do for the time, and they are ALL defined in the includes for
easy standardization for future specifications!
thats my 2 cents,
Xeg...@shell.portal.com
>In article <3547vr$6...@wsinti05.info.win.tue.nl>,
>Hans Mulder <ha...@win.tue.nl> wrote:
>>In <CvMpI...@inter.NL.net> m...@inter.NL.net (Miguel Carrasquer) writes:
>> > There are other non-standard features about the Amiga. My
>> > favourite one was that you could determine if your program
>> > had been started up from the CLI or from a Workbench icon
>> > by declaring:
>> > main(argc, argv)
>> > int argc;
>> > char **argv;
>> > {
>> > if(argc==0) {
>> > /* Workbench stuff */
>> > } else {
>> > /* CLI stuff */
>> > }
>> > ...
>> > }
>>In what way is that non-standard?
>>AFAIK, the standard does not promise that argc > 0,
>>nor that *argv points at anything in particular.
>This stuff (AmigaOS) was written well before the ANSI
>standard. I meant non-standard in the sense that
>argc==0 cannot happen in unix (or any other system I
>know of).
It *can* happen in unix: if you run
int main() {
static char *none[]={0};
execve("/bin/csh", none, none);
return 1;
}
the C shell will be called with an argc value of 0.
It'll then dump core, because the author of the C shell shares
your belief that it cannot happen.
--
HansM ha...@win.tue.nl
If a function be advertised to return an error code in the event
of difficulties, thou shalt check for that code, yea, even though
the checks triple the size of thy code and produce aches in thy
typing fingers, for if thou thinkest ``it cannot happen to me'',
the gods shall surely punish thee for thy arrogance.
-- Henry Spencer, "The Ten Commandments for C Programmers"
>Yeah if the program is exec'd by another program where it is the user's respon-
>sibility to decide which arguments are passed, but never when the program is
>begun by the OS.
The *only* program started by the Unix kernel is the one run in the very
first process the Unix kernel creates. All other programs are run by other
user programs. Now some of these programs may happen to be system supplied
shells but there is no requirement at all that you use these (and indeed
many people have switched over to alternatives).
>In that case argv[0] always contains the name of the program
>and argc is at least equal to 1 if no additional arguments were passed.
>This is the standard way things are done.
This is merely a convention, not a standard. A program should always
be able to cope with the situation where it is called with argc == 0,
even if that means exiting cleanly with an error.
>Date: 20 Sep 1994 21:16:11 +0200
>Organization: Eindhoven University of Technology, The Netherlands
>Lines: 54
>Message-ID: <35ncdr$e...@wsinti05.info.win.tue.nl>
>If a function be advertised to return an error code in the event
>of difficulties, thou shalt check for that code, yea, even though
>the checks triple the size of thy code and produce aches in thy
>typing fingers, for if thou thinkest ``it cannot happen to me'',
>the gods shall surely punish thee for thy arrogance.
> -- Henry Spencer, "The Ten Commandments for C Programmers"
^^^^^ ^^^^^^^^^^^^^
Do you happen to have the other nine? I would like to post them in the
computer room I work at.
Thanx
Victor
>In article <35ncdr$e...@wsinti05.info.win.tue.nl> ha...@wsinti05.info.win.tue.nl (Hans Mulder) writes:
>
>> -- Henry Spencer, "The Ten Commandments for C Programmers"
>
>Do you happen to have the other nine? I would like to post them in the
>computer room I work at.
The Ten Commandments for C Programmers
Henry Spencer
1. Thou shalt run lint frequently and study its pronouncements
with care, for verily its perception and judgement oft exceed thine.
2. Thou shalt not follow the NULL pointer, for chaos and madness
await thee at its end.
3. Thou shalt cast all function arguments to the expected type if
they are not of that type already, even when thou art convinced that
this is unnecessary, lest they take cruel vengeance upon thee when thou
least expect it.
4. If thy header files fail to declare the return types of thy
library functions, thou shalt declare them thyself with the most
meticulous care, lest grievous harm befall thy program.
5. Thou shalt check the array bounds of all strings (indeed, all
arrays), for surely where thou typest 'foo' someone someday shall
type 'supercalifragilisticexpialidocious'.
6. If a function be advertised to return an error code in the event
of difficulties, thou shalt check for that code, yea, even though the
checks triple the size of thy code and produce aches in thy typing
fingers, for if thou thinkest 'it cannot happen to me', the gods
shall surely punish thee for thy arrogance.
7. Thou shalt study thy libraries and strive not to re-invent them
without cause, that thy code may be short and readable and thy days
pleasant and productive.
8. Thou shalt make thy program's purpose and structure clear to thy
fellow man by using the One True Brace Style, even if thou likest it
not, for thy creativity is better used in solving problems than in
creating beautiful new impediments to understanding.
9. Thy external identifiers shall be unique in the first six
characters, though this harsh discipline be irksome and the years of
its necessity stretch before thee seemingly without end, lest thou tear
thy hair out and go mad on that fateful day when thou desirest to make
thy program run on an old system.
10. Thou shalt foreswear, renounce, and abjure the vile heresy which
claimeth that 'All the world's a VAX', and have no commerce with the
benighted heathens who cling to this barbarous belief, that the days of
thy program may be long even though the days of thy current machine be
short.
What if you don't have an ANSI lint? !@#*!@#*!@#*. (I have one which
chokes on prototypes, not to mention ##'s.)
>2. Thou shalt not follow the NULL pointer, for chaos and madness
>await thee at its end.
How about the offsetof trick (&((struct foo *) 0)->bar)?
>4. If thy header files fail to declare the return types of thy
>library functions, thou shalt declare them thyself with the most
>meticulous care, lest grievous harm befall thy program.
Please, not this... I've had to spend days, if not weeks, fixing
programs that meticulously declared library functions to their
correct types - for some system. It's worse when they're #ifdeffed
for many systems, because, through simple Murphy, you know* that
your system will end up needing 90% BSD declarations and 10% SYSV,
or something like that.
>6. If a function be advertised to return an error code in the event
>of difficulties, thou shalt check for that code, yea, even though the
>checks triple the size of thy code and produce aches in thy typing
>fingers, for if thou thinkest 'it cannot happen to me', the gods
>shall surely punish thee for thy arrogance.
Hear, hear.
>7. Thou shalt study thy libraries and strive not to re-invent them
>without cause, that thy code may be short and readable and thy days
>pleasant and productive.
If I had a nickel for every time a programmer where I worked did
char buf[arbitrary_fixed_constant size];
sprintf(buf, "rm -f %s", file_name);
system(buf);
I'd be buying that X terminal I want.
>8. Thou shalt make thy program's purpose and structure clear to thy
>fellow man by using the One True Brace Style, even if thou likest it
>not, for thy creativity is better used in solving problems than in
>creating beautiful new impediments to understanding.
(I agree, although I'd like to shoot the yahoo that declared that braces
were at *3* spaces, guaranteeing that you couldn't tab to them or shift
by them on HP's vi.)
>9. Thy external identifiers shall be unique in the first six
>characters, though this harsh discipline be irksome and the years of
>its necessity stretch before thee seemingly without end, lest thou tear
>thy hair out and go mad on that fateful day when thou desirest to make
>thy program run on an old system.
*sigh* Irritating, but needed.
>10. Thou shalt foreswear, renounce, and abjure the vile heresy which
>claimeth that 'All the world's a VAX', and have no commerce with the
>benighted heathens who cling to this barbarous belief, that the days of
>thy program may be long even though the days of thy current machine be
>short.
Hear, hear.
>Dan Pop
>CERN, CN Division
>Email: dan...@cernapo.cern.ch
>Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland
Thanks. Those are beautiful. Is the original author around? I think
the one about headers should be ammended to inform people to first*
try to use the headers, because people have a deadly tendancy to just
throw "extern [short,long,int,unsigned int, ...] errno;" and "extern
char *sys_errlist[]" in allegedly portable code.
>>2. Thou shalt not follow the NULL pointer, for chaos and madness
>>await thee at its end.
>
>How about the offsetof trick (&((struct foo *) 0)->bar)?
>
This trick is not guaranteed to work (at least, not by the ANSI standard).
If you find it in your compiler's header files, it means that the trick
works on your compiler (where void main might work, as well :-), not
that it is a valid C construct. Even the next version of your compiler
might not support it and provide a different implementation for offsetof.
Dan
--
>This trick is not guaranteed to work (at least, not by the ANSI standard).
>If you find it in your compiler's header files, it means that the trick
>works on your compiler (where void main might work, as well :-), not
>that it is a valid C construct. Even the next version of your compiler
>might not support it and provide a different implementation for offsetof.
I was told at one point that you were* allowed to do that, as long as you
didn't actually reference* foo->bar, and that the address was guaranteed
to be the offset. I don't think it was in a schildt book, either. Anyone
got any idea where I would have gotten this, or a standard quote that
specifically allows or disallows it?
I had figured it was of the same genre as i[a].
>Dan
>CERN, CN Division
>Email: dan...@cernapo.cern.ch
>Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland
-seebs
>In article <Cx1q4...@news.cern.ch> dan...@cernapo.cern.ch (Dan Pop) writes:
>>In <36lbpa$k...@blackice.winternet.com> se...@solutions.solon.com (Peter Seebach) writes:
>>>How about the offsetof trick (&((struct foo *) 0)->bar)?
>
>>This trick is not guaranteed to work (at least, not by the ANSI standard).
>>If you find it in your compiler's header files, it means that the trick
>>works on your compiler (where void main might work, as well :-), not
>>that it is a valid C construct. Even the next version of your compiler
>>might not support it and provide a different implementation for offsetof.
>
>I was told at one point that you were* allowed to do that, as long as you
>didn't actually reference* foo->bar, and that the address was guaranteed
>to be the offset. I don't think it was in a schildt book, either. Anyone
>got any idea where I would have gotten this, or a standard quote that
>specifically allows or disallows it?
>
>I had figured it was of the same genre as i[a].
I can't tell where you got this idea from, but I can clarify the matter
a little bit by posting a quote from the Rationale:
: In many implementations, offsetof could be defined as one of
:
: (size_t)&(((s_name*)0)->m_name)
:
: or
:
: (size_t)(char *)&(((s_name*)0)->m_name)
:
: or, where X is some predeclared address (or 0) and A(Z) is defined as
: ((char*)&Z),
:
: (size_t)( A( (s_name*)X->m_name ) - A( X ))
:
: It was not feasible, however, to mandate any single one of these forms as a
: construct guaranteed to be portable. Other implementations may choose to
: expand this macro as a call to a built-in function that interrogates the
: translator's symbol table.
Dan
--
Dan Pop
--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91351-4454 96.37% of all statistics are made up
>Which compilers won't accept the "standard" offsetof macro?
Which compilers won't accept the "standard" void main() definition?
>What if you don't have an ANSI lint? !@#*!@#*!@#*. (I have one which
>chokes on prototypes, not to mention ##'s.)
A good modern compiler will tell you many of the same things that you
used to need lint for.
>>2. Thou shalt not follow the NULL pointer...
>
>How about the offsetof trick (&((struct foo *) 0)->bar)?
Not fully portable. Merely trying to compute that address may be a fatal
error. Only the implementor can tell you how to write offsetof() safely,
which is why it's required to be part of the implementation.
>>4. If thy header files fail to declare the return types of thy
>>library functions, thou shalt declare them thyself with the most
>>meticulous care, lest grievous harm befall thy program.
>
>Please, not this... I've had to spend days, if not weeks, fixing
>programs that meticulously declared library functions to their
>correct types - for some system...
Believe me, I understand the problem, but it's better than having the
author say "enh, the default type is int, and I know long is the same size,
so I won't bother declaring atol() at all". Error messages are better
than no error messages...
>... Is the original author around? I think
>the one about headers should be ammended to inform people to first*
>try to use the headers, because people have a deadly tendancy to just
>throw "extern [short,long,int,unsigned int, ...] errno;" and "extern
>char *sys_errlist[]" in allegedly portable code.
I put out an annotated edition a while ago which elaborated on some
of the points, and it comments on this.
--
Justice for groups that doesn't include justice | Henry Spencer
for individuals is a mockery. | he...@zoo.toronto.edu
>In <36pmf5$r...@trans.jpl.nasa.gov> k...@trans.jpl.nasa.gov (Kevin D. Quitt) writes:
>
>>Which compilers won't accept the "standard" offsetof macro?
>
>Which compilers won't accept the "standard" void main() definition?
I missed the front of this thread, but the Standard does require an
'offsetof' macro (in stddef.h). Thus your response seems to be
something of a non sequitur.
If the original question was with regard to some standard way to *write*
that macro, then there indeed is not one. However, there must be a
NONportable way to write such a macro, whereas there is no requirement
that there be a nonportable way to make 'void main()' work (so your
response is still a non sequitur).
--
"Insisting on perfect safety is for people who don't have the balls to live
in the real world." -- Mary Shafer, NASA Ames Dryden
---------------------------------------------------------------------------
mer...@annwfn.com -- I don't speak for others and they don't speak for me.
>In <Cx549...@news.cern.ch> dan...@cernapo.cern.ch Dan Pop writes:
>
>>In <36pmf5$r...@trans.jpl.nasa.gov> k...@trans.jpl.nasa.gov (Kevin D. Quitt) writes:
>>
>>>Which compilers won't accept the "standard" offsetof macro?
>>
>>Which compilers won't accept the "standard" void main() definition?
>
>I missed the front of this thread, but the Standard does require an
>'offsetof' macro (in stddef.h). Thus your response seems to be
>something of a non sequitur.
>
>If the original question was with regard to some standard way to *write*
>that macro, then there indeed is not one. However, there must be a
>NONportable way to write such a macro, whereas there is no requirement
>that there be a nonportable way to make 'void main()' work (so your
>response is still a non sequitur).
If you miss the beginning of a thread, the best thing you can do is to
avoid joining it later. Here is what started this discussion:
: >2. Thou shalt not follow the NULL pointer, for chaos and madness
: >await thee at its end.
:
: How about the offsetof trick (&((struct foo *) 0)->bar)?
During the thread it was already pointed out that the definition of
offsetof is inherently non-portable.
Also, you seem to have completely ignored the double quotes surrounding
the word standard in the text you've quoted.