Topic: Legal Prototypes for the "main" Function
Author: gordon@sneaky.lonestar.org (Gordon Burditt)
Date: Thu, 9 Sep 1993 18:56:46 GMT Raw View
> One should realize that argc is passed as an "int" in all of the
>POSIX.1 "exec" variations. I think POSIX.1 is wrong here too, but they were
>simply going along with American National Standard X3.159-1989 (in addition to
>UNIX common practice). Anyway, since American National Standard X3.159-1989
>guarantees that a negative argc cannot be passed to main(), this should pose no
>problem to POSIX.1. (Or does POSIX.1 allow passing negative integers to exec functions?)
What POSIX.1 exec* functions take any integer (signed, unsigned,
any size) arguments at all? The ones in my book must calculate argc
from the passed arguments, as argc isn't passed, and as far as I
know it's not possible to pass a negative number of varargs arguments
to functions like execl(), or a negative number of character pointers
in a NULL-pointer-terminated list.
Gordon L. Burditt
sneaky.lonestar.org!gordon
Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Mon, 13 Sep 1993 03:02:06 GMT Raw View
davisonj@bnr.ca (John M Davison) writes:
> Fergus Henderson writes:
>
>> But this is wrong, because static functions can only be called by other
>> functions in their compilation unit, but main() gets called by the
>> startup code or the operating system - which is clearly not part of the
>> compilation unit.
[...]
>> I doubt [that the ability to use the keyword "static" with "main" would
>> discourage the recursive usage of main].
>
> Why not?
Because recursive usage of main() is 99.9% confined to the obfuscated C
competition and the C conciseness competition, and competitors in these
competitions will probably avoid using the keyword static whether they
call main() recursively or not (why waste 7 characters of source code? :-)
>> But what's wrong with using main recursively anyway?
>> Why do you want to discourage it?
>
> Certainly one can imagine situations in which calling main recursively
>would not be sensible, i.e. most of the C programs in existence. Allowing
>"static" as a modifier for main() would provide a facility for additional
>access control in C/C++ without substantially enlarging or obfuscating the
>language.
>
> In cases in which it is desirable to call main() from routines outside
>the compilation unit (let's ingore the issue of whether X3.159-1989 would
>permit calling main from an internal startup routine), don't use the "static"
>modifier.
I don't think it's fair to ignore that issue, because to me at least,
and probably to many others, it intuitively makes little sense to allow
it, and allowing it as a special exception would be counter-productive
because it would increase the language complexity by far more than it's
worth.
You seem to want a module system that is more expressive than C's - in
particular, you want to be able to state that some routine (in this case
main()) should be callable by some module other than the current module
(in this case, by the operating system or startup code) but only by
that specified other module and not by anything else.
This sounds like a reasonable idea in general, but C doesn't really
have much of a module system, and is not really up to the task, while
C++ now has already three separate means for introducing modularity
(static, as in C; private/protected; and namespaces) and is already
complex enough. Perhaps you should consider some other language?
--
Fergus Henderson fjh@munta.cs.mu.OZ.AU
Author: diamond@jit.dec.com (Norman Diamond)
Date: 6 Sep 1993 05:10:52 GMT Raw View
Followups to two articles here.
In article <268h5v$l4@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
> I wrote:
>>>The following prototype, however, would seem to be much more sensible:
>>> int main(size_t numofArgs, const char * const * const arrayOfArgs);
> Norman Diamond writes:
>>The first const would not be sensible because programs are allowed to modify
>>the strings that the argv array elements point to...
> There is an error in Diamond's logic here: programs are allowed, but
>not required, to modify the strings to which the argv array elements point.
I don't see the error. Programs are allowed to modify the strings, exactly
as I said. Most don't and they are legal. Even those that do, still don't
quite get there instantaneously (thereby revealing passwords in command lines
to users of the "ps" command who get lucky with timing, etc.).
>>...the last const would be gratuitous -- if other functions can modify their
>>own variables that are received as parameters, then why should main() be
>>restricted?
> Programmer's prerogative.
Well, you finally made it clear later in your current posting, you wanted
your "much more sensible" prototype to be an additional alternative rather
than a replacement, i.e. that it is SOMETIMES more sensible. Sure, if the
programmer is given a prerogative, it will be programmer's prerogative.
> It has been shown in this thread that there are certainly cases in which
>it would be desirable to have argc be in excess of MAX_INT.
That hasn't been shown. It has been shown that there are cases in which
it is desirable to have argc be in excess of 32767, but by coincidence those
cases also have INT_MAX around two billion.
>Using an int is potentially confusing, and exists for historical reasons alone.
The C language is confusing, and should only exist for historical reasons
alone. (C++ is even worse. Why do people still insist on using C or C++
for new developments? Sigh.)
>>> If I'm not calling "main" recursively or using it in any other funny
>>>manner, I would prefer the following:
>>> static int main(size_t numofArgs,
>>> const char * const * const arrayOfArgs);
>> I think "static" would not be sensible, for the same reason as making the
>> declarations of library functions say "static" would not be sensible.
> This would help discourage the recursive usage of main; would it not?
Static functions can be called recursively within the same translation unit.
The actual genuine discouragement for calling main() recursively is that
there's rarely any convenient method of doing so, let alone any purpose.
>> Pedantically, implementations could be made to work despite this misleading
>> formality of syntax (after all, they already do so with "static" functions
>> anyway), but why bother?
> How is this misleading?
Because you really want main() to be externally visible to the part of the
C implementation or operating system that calls it. The details aren't
part of the standard, and it would be possible to fudge the formalities of
this stuff to conform to a misleading hypothetical standard and still get
the results right, but it would still be misleading.
[Regarding C++]
>Extending the set of acceptable prototypes for main() to include the prototypes
>I mentioned would allow and encourage greater type-consistency in programs,
>break no previous ARM-compliant C++ code (or conforming C code) whatsoever, and
>require minimal effort from compiler writers.
Especially now that you've said you want additional alternatives, rather than
replacements, I would agree that this makes sense. I suggest that you add it
to the g++ compiler, and then present the case of (then) existing art to the
C++ committee.
In article <4SEP199303595727@lando.hns.com> hsspes1@lando.hns.com (Ajoy KT of PES GROUP AT HSS) writes:
> Going on a tangent, does the standard, either implicitly or explicitly,
>require that the call to main() should *not* depend on the way the user has
>declared his main() function? That is, if the user declares main as
>int main(void), is the implementation free _not_ to pass the command-line
>arguments to the program. I believe this should be so, but I am not sure.
If the user has declared int main(void) then the implementation cannot
pass the command-line arguments to the program. There is no freedom.
> If that is indeed so, then allowing the argc and argv parameters of
>main() to be declared as const _does_ certainly help. The implementation may,
>for example, put the argv array in read only storage.
If the user has declared int main(void) then the implementation doesn't
put the array anywhere.
--
<< If this were the company's opinion, I would not be allowed to post it. >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will. Force = program size * destruction.
Author: davisonj@bnr.ca (John M Davison)
Date: 3 Sep 1993 22:41:03 GMT Raw View
I wrote:
>Section 2.1.2.2.1 ("Program Startup") says that each of these two prototypes
> int main(void);
> int main(int numOfArgs, char *arrayOfArgs[]);
>The following prototype, however, would seem to be much more sensible:
> int main(size_t numofArgs, const char * const * const arrayOfArgs);
Norman Diamond writes:
> The first const would not be sensible because programs are allowed to modify
> the strings that the argv array elements point to...
There is an error in Diamond's logic here: programs are allowed, but
not required, to modify the strings to which the argv array elements point.
Norman Diamond writes:
> ...the last const would be gratuitous -- if other functions can modify their
> own variables that are received as parameters, then why should main() be
> restricted?
Programmer's prerogative.
> Even you didn't restrict the argc parameter that way.
That possibility should be considered too.
> The middle const would be sensible and its sole effect would be to require
> rewriting of nearly all existing code. (So now you know why that one was
> omitted too.)
Here, Norman mistakenly assumed that I am proposing these new
prototypes as a replacement, rather than an addition, to the already-accepted
prototypes.
Norman Diamond writes:
> It might be sensible to make the argc parameter size_t instead of int, but
> I think it will be a long (:-) time before we see operating systems that
> permit passing more than 32767 strings in a command line, or invokers who
> wish to pass such.
It has been shown in this thread that there are certainly cases in which
it would be desirable to have argc be in excess of MAX_INT.
Furthermore, allowing size_t would encourage greater uniformity in those
main()'s where the usage of size_t would be sensible. size_t is already used
in the standard library as a generic array size/index parameter; argc's
function in main() is to act as an array size parameter. Using an int is
potentially confusing, and exists for historical reasons alone. (Name one good
reason for using an int instead of a size_t that doesn't appeal to prior art.)
I wrote:
> If I'm not calling "main" recursively or using it in any other funny
>manner, I would prefer the following:
> static int main(size_t numofArgs,
> const char * const * const arrayOfArgs);
Norman Diamond writes:
> I think "static" would not be sensible, for the same reason as making the
> declarations of library functions say "static" would not be sensible.
This would help discourage the recursive usage of main; would it not?
Norman Diamond writes:
> Pedantically, implementations could be made to work despite this misleading
> formality of syntax (after all, they already do so with "static" functions
> anyway), but why bother?
How is this misleading?
Why bother? Tighter, cleaner, harder-to-screw-up C code. (Or does
this violate the "Spirit of C"?)
I wrote:
> If I were calling it from, say, a POSIX.1 "exec..." call, I might
>prefer to use
> static int main(int numofArgs,
> const char * const * const arrayOfArgs);
Norman Diamond writes:
> Returning argc's type to int instead of size_t, but otherwise identical to
> your previous suggestion? Your suggestions seem a bit incoherent.
One should realize that argc is passed as an "int" in all of the
POSIX.1 "exec" variations. I think POSIX.1 is wrong here too, but they were
simply going along with American National Standard X3.159-1989 (in addition to
UNIX common practice). Anyway, since American National Standard X3.159-1989
guarantees that a negative argc cannot be passed to main(), this should pose no
problem to POSIX.1. (Or does POSIX.1 allow passing negative integers to exec functions?)
I wrote:
> Are the proposed C++ rules regarding the "main" prototype different
>than the C rules established in American National Standard X3.159-1989?
Norman Diamond writes:
> The proposed rules in Ellis & Stroustrop are the same as for C. (This is
> not necessarily the current answer.)
Someone else wrote:
>While we're on the subject, does anyone know why argc is not "unsigned int"?
Norman Diamond writes:
> Maybe no one noticed before that this could be done without breaking any code
> and without adding any further burden to making implementations conform.
This is exactly why I am cross-posting this article to comp.std.c++.
Extending the set of acceptable prototypes for main() to include the prototypes
I mentioned would allow and encourage greater type-consistency in programs,
break no previous ARM-compliant C++ code (or conforming C code) whatsoever, and
require minimal effort from compiler writers.
--
+--------+ main() { const char c = 'c'; char *pc; const char **pcc = &pc;
|John | *pcc = &c; *pc = 'C'; } // Whoops!
|Davison | Disclaimer: The information contained in this article is not
+--------+ representative of Northern Telecom and/or BNR.
Author: davisonj@bnr.ca (John M Davison)
Date: 3 Sep 1993 22:11:50 GMT Raw View
In article <xtifrCCr7wp.E8@netcom.com> xtifr@netcom.com (Chris Waters) writes:
>I don't see what relevance 32767 has to
>ints! Except, perhaps on messy-DOG systems. :-)
Clearly, Mr./Mrs./Ms. Chris Waters is not acquainted with American
National Standard X3.159-1989, Appendix D.
--
+--------+ main() { const char c = 'c'; char *pc; const char **pcc = &pc;
|John | *pcc = &c; *pc = 'C'; } // Whoops!
|Davison | Disclaimer: The information contained in this article is not
+--------+ representative of Northern Telecom and/or BNR.
Author: jason@cygnus.com (Jason Merrill)
Date: Sun, 5 Sep 1993 03:28:56 GMT Raw View
>>>>> davisonj@bnr.ca (John M Davison) writes:
>> I think "static" would not be sensible, for the same reason as making the
>> declarations of library functions say "static" would not be sensible.
> This would help discourage the recursive usage of main; would it not?
And it would encourage the use of "main" in other modules, would it not?
Are we going to force the linker to recognize that main should be protected
against multiple definitions, even though it is local to a particular
module? This seems to be vastly more trouble than it's worth.
Author: msb@sq.sq.com (Mark Brader)
Date: Sat, 4 Sep 93 03:04:47 GMT Raw View
> (Name one good reason for using an int instead of a size_t ...
It gives you the flexibility to let the variable to go -1 in a loop,
if that happens to suit your convenience. For example, this code prints
the command name and all arguments:
while (--argc >= 0) printf ("%s\n", *argv++);
If argc had an unsigned type such as size_t, that wouldn't work.
Yes, of course there are other ways to write it, and it isn't something
you do all that often anyway. The thing is that unsigned types can be
tricky in C, and one often wants to avoid them.
> ... that doesn't appeal to prior art.)
I fail to see the logic of not appealing to prior art in a discussion
about the standard.
--
Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
#define MSB(type) (~(((unsigned type)-1)>>1))
This article is in the public domain.
Author: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Date: 7 Sep 93 04:17:44 GMT Raw View
In article <268h5v$l4@crchh327.bnr.ca>, davisonj@bnr.ca (John M Davison) writes:
> One should realize that argc is passed as an "int" in all of
> the POSIX.1 "exec" variations. I think POSIX.1 is wrong here too, but
> they were simply going along with American National Standard X3.159-1989
> (in addition to UNIX common practice). Anyway, since American National
> Standard X3.159-1989 guarantees that a negative argc cannot be passed to
> main(), this should pose no problem to POSIX.1. (Or does POSIX.1 allow
> passing negative integers to exec functions?)
Hang on a minute. The POSIX.1 "exec" variations are, according to
AS 3976.1-1991 (= ISO/EIC 9945-1:1990) section 3.1.2.1
int execl( const char *path, const char *arg, ...);
int execle(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execv( const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvp(const char *file, char *const argv[]);
In **none** of these functions is argc passed as *anything*, still less
as an "int". In each of these variants, the end of the argument list is
determined by the presence of a NULL argument pointer. So it isn't
POSIX.1 that is wrong, but John M. Davison's memory.
Note that POSIX.1 requires only that _POSIX_ARG_MAX be at least 4096, so a
portable POSIX application cannot _depend_ on more than 4096 *characters*
of arguments, for which an 'int' argc is more than ample. What benefit
is it if you have a 64-bit unsigned argc, but ARG_MAX is 5000? POSIX.1 +
ANSI C would allow that.
What about main()? POSIX.1 says
When a C program is executed as a result of this [exec] call,
it shall be entered as a C language function call as follows:
int main(int argc, char *argv[]);
where argc is the argument count and argv is an array of character
pointers to the arguments themselves. In addition, the following
variable:
extern char **environ;
is initialised as a pointer to an array of character pointers to
the environment stringhs. The argv and environ arrays are each
terminated by a NULL pointer. The NULL pointer terminating the
argv array is not counted in argc.
POSIX.1 makes plain that the initial value of argc will be at least 1,
but warns that some "historical implementations" occasionally passed 0.
I can find nothing in POSIX.1 that would allow negative values of argc.
There is one extremely simple reason why POSIX.1 did not and could not
require size_t; size_t wasn't in K&R and they didn't want to _require_
the use of ANSI C.
I recommend reading the relevant section of the rationale, B.3.1.2
lines 1887--1909. Basically, the point is that *no* combination of
"consts" would permit existing correct code to continue working.
The Rationale makes it perfectly clear that "these objects [argv,envv]
are completely constant" (that is, the exec* functions themselves do not
modify them). It does not comment on main(), but apart from the fact
that existing code in "historical impleentations" has been allowed to
modify the argument vector (amongst other things, in an attempt to
eliminate a covert channel), it would again be impossible for the
standard to impose any pattern of consts without breaking existing code.
By the way, when the ANSI C standard became the ISO C standard, we were
told that the Rationale had to be dropped because ISO standards couldn't
have Rationales. But here is POSIX.1 where appendix B not only _is_ a
Rationale, it's _called_ a Rationale, and it occupies approximately one
third of the total number of pages. I'm very glad to have that Rationale;
it makes a lot of things clear. So why couldn't the ISO C standard have
had just such an appendix?
--
Richard A. O'Keefe; ok@goanna.cs.rmit.oz.au; RMIT, Melbourne, Australia.
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 7 Sep 1993 09:12:11 GMT Raw View
davisonj@bnr.ca (John M Davison) writes:
>> If I'm not calling "main" recursively or using it in any other funny
>>manner, I would prefer the following:
>> static int main(size_t numofArgs,
>> const char * const * const arrayOfArgs);
But this is wrong, because static functions can only be called by other
functions in their compilation unit, but main() gets called by the
startup code or the operating system - which is clearly not part of the
compilation unit.
> Norman Diamond writes:
>
>> I think "static" would not be sensible, for the same reason as making the
>> declarations of library functions say "static" would not be sensible.
>
> This would help discourage the recursive usage of main; would it not?
I doubt it. But what's wrong with using main recursively anyway?
Why do you want to discourage it?
Author: jfw@ksr.com (John F. Woods)
Date: 7 Sep 93 16:07:39 EDT Raw View
xtifr@netcom.com (Chris Waters) writes:
>Hmm, on any *reasonable* system, an int will hold approx +-2 billion,
>so this shouldn't be an issue on most machines that *have* a
>/var/spool/news directory. I don't see what relevance 32767 has to
>ints! Except, perhaps on messy-DOG systems. :-)
Ahem. The PDP-11, still servicable as a news machine if showing its age now,
traditionally uses 16-bit ints.
Author: jfw@ksr.com (John F. Woods)
Date: 7 Sep 93 16:10:43 EDT Raw View
davisonj@bnr.ca (John M Davison) writes:
>(Name one good
>reason for using an int instead of a size_t that doesn't appeal to prior art.)
Name one good reason for not appealing to prior art. (Hint: so far, you
haven't.) For extra credit, name one reason for not appealing to prior art
that is *good enough* to break every existing C program prior to making this
change.
Author: davisonj@bnr.ca (John M Davison)
Date: 8 Sep 1993 20:16:04 GMT Raw View
I incorrectly wrote:
> ...argc is passed as an "int" in all of the POSIX.1 "exec" variations.
Richard A. O'Keefe writes:
> Hang on a minute. The POSIX.1 "exec" variations are, according to
> AS 3976.1-1991 (= ISO/EIC 9945-1:1990) section 3.1.2.1
>
> int execl( const char *path, const char *arg, ...);
> int execle(const char *path, const char *arg, ...);
> int execlp(const char *file, const char *arg, ...);
> int execv( const char *path, char *const argv[]);
> int execve(const char *path, char *const argv[], char *const envp[]);
> int execvp(const char *file, char *const argv[]);
I was wrong. Not only does exec not explicitly pass a user-supplied
int, but since argc is derived from the argv parameter, size_t clearly supports
the entire range of values that main's argc may have (ANSI X3.159-1989, Section
4.1.5, lines 14-15; ANSI X3.159-1989, Section 3.3.3.4; ANSI X3.159-1989,
Section 2.1.2.2.1, lines 3-11).
Note that what I am proposing would require a revision of ANSI
X3.159-1989, Section 2.1.2.2.1, lines 16-17.
Richard A. O'Keefe goes on to write:
> What benefit is it if you have a 64-bit unsigned argc, but ARG_MAX is 5000?
None, but C doesn't revolve around UNIX (or POSIX) anymore.
Furthermore, POSIX does not mandate an upper limit on ARG_MAX. (On the other
hand, ISO/IEC 9945-1:1990 does say that "Implementations claiming conformance
using Common-Usage [i.e. K&R] C may...use int when a function result is
declared ssize_t." I cannot find anything in ISO/IEC 9945-1:1990 that says
that the range representable by size_t (ie. -1 to SSIZE_MAX) must be a proper
subset of the range representable by ssize_t, however. Clarification, anyone?
> There is one extremely simple reason why POSIX.1 did not and could not
> require size_t; size_t wasn't in K&R and they didn't want to _require_
> the use of ANSI C.
This is beyond the scopes of comp.std.c and comp.std.c++.
> I recommend reading the relevant section of the rationale, B.3.1.2
> lines 1887--1909.
Lines 1887-1909 show that POSIX.1 is taking the safe approach that
would successfully handle all "const" combinations in the "main" signature by
assuming as little as possible, "Due to a limitation of the C Standard" -- the
very limitation that we are discussing in this thread, namely the inability of
a C (or C++) programmer to express (and, of course, impose) constness of the
parameters for a particular "main" if desired.
If this limitation -- described in lines 1890-1893 -- were to be
removed from C and/or C++, POSIX.1 "exec" calls would still work fine.
> Basically, the point is that *no* combination of
> "consts" would permit existing correct code to continue working.
O'Keefe's summary of those lines is incorrect, since he (evidently)
reasons, and wrongly so, that an assumption of constness on behalf of a called
routine necessitates that assumption of constness on behalf of the caller.
Fergus Henderson writes:
> But this is wrong, because static functions can only be called by other
> functions in their compilation unit, but main() gets called by the
> startup code or the operating system - which is clearly not part of the
> compilation unit.
True, and X3.159-1989, Section 3.1.2.2, Line 10 even says that a "set
of translation units and libraries...constitutes [a] program", but I'm not sure
where the startup code fits into this -- is X3.159-1989 explicit about it? (If
so, where?)
> I doubt [that the ability to use the keyword "static" with "main" would
> discourage the recursive usage of main].
Why not?
> But what's wrong with using main recursively anyway?
> Why do you want to discourage it?
Certainly one can imagine situations in which calling main recursively
would not be sensible, i.e. most of the C programs in existence. Allowing
"static" as a modifier for main() would provide a facility for additional
access control in C/C++ without substantially enlarging or obfuscating the
language.
In cases in which it is desirable to call main() from routines outside
the compilation unit (let's ingore the issue of whether X3.159-1989 would
permit calling main from an internal startup routine), don't use the "static"
modifier.
John F. Woods writes:
> Name one good reason for not appealing to prior art.... name one reason for
> not appealing to prior art that is *good enough* to break every existing C
> program prior to making this change.
See article <26dfp0$a5k@crchh327.bnr.ca> for the appropriate rebuttals.
--
+--------+
|John | "Who says MS-DOS isn't multitasking? You
|Davison | just need one box per task!"
+--------+ -- Mike Meyer, mwmeyer@ingres.com
Author: davisonj@bnr.ca (John M Davison)
Date: 1 Sep 1993 22:28:59 GMT Raw View
American National Standard X3.159-1989, Section 2.1.2.2.1 ("Program
Startup") says that each of these two prototypes is a permissible prototype for
the C "main" function:
int main(void);
int main(int numOfArgs, char *arrayOfArgs[]);
The following prototype, however, would seem to be much more sensible:
int main(size_t numofArgs, const char * const * const arrayOfArgs);
If I'm not calling "main" recursively or using it in any other funny
manner, I would prefer the following:
static int main(size_t numofArgs,
const char * const * const arrayOfArgs);
If I were calling it from, say, a POSIX.1 "exec..." call, I might
prefer to use
static int main(int numofArgs,
const char * const * const arrayOfArgs);
Of course, I might also want to use other variations:
int main();
static int main();
main();
etc.
A quick read through Section 2.1.2.2.1 would seem to indicate that the
only two acceptable prototypes are the two I listed above. Is this the case?
(I should hope not!)
Is there any way to express the "constness" configuration of the
"arrayOfArgs" parameter using the more readable "[]" syntax instead of all
those *'s? I can't seem to figure out a way, and judging by the fact that the
USL C++ Class Library documentation does it the way I do it (i.e. with the "*"
notation all the way through), I get the feeling that neither C nor C++
supports this.
Are the proposed C++ rules regarding the "main" prototype different
than the C rules established in American National Standard X3.159-1989?
--
+--------+ main() { const char c = 'c'; char *pc; const char **pcc = &pc;
|John | *pcc = &c; *pc = 'C'; } // Whoops!
|Davison | Disclaimer: The information contained in this article is not
+--------+ representative of Northern Telecom and/or BNR.
Author: fouts@cello.hp.com (Marty Fouts)
Date: Wed, 1 Sep 1993 22:52:41 GMT Raw View
The reason why
static int main(size_t argc,
const char * const * const argv)
is not always more reasonable than
int main(int argc, char *Argv[]);
is that there is common practice, which causes argc and argv to be
modified. X windows, for example, parses the arg list, removing the
arguments it recognizes and then leaves the rest for the application
to deal with as it sees fit.
Marty
--
Martin Fouts
fouts@hpl.hp.com
Author: diamond@jit.dec.com (Norman Diamond)
Date: 2 Sep 1993 01:02:31 GMT Raw View
In article <2637nb$h30@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
>Section 2.1.2.2.1 ("Program Startup") says that each of these two prototypes
> int main(void);
> int main(int numOfArgs, char *arrayOfArgs[]);
>The following prototype, however, would seem to be much more sensible:
> int main(size_t numofArgs, const char * const * const arrayOfArgs);
The first const would not be sensible because programs are allowed to modify
the strings that the argv array elements point to, and the last const would
be gratuitous -- if other functions can modify their own variables that are
received as parameters, then why should main() be restricted? Even you
didn't restrict the argc parameter that way.
The middle const would be sensible and its sole effect would be to require
rewriting of nearly all existing code. (So now you know why that one was
omitted too.)
It might be sensible to make the argc parameter size_t instead of int, but
I think it will be a long (:-) time before we see operating systems that
permit passing more than 32767 strings in a command line, or invokers who
wish to pass such.
> If I'm not calling "main" recursively or using it in any other funny
>manner, I would prefer the following:
> static int main(size_t numofArgs,
> const char * const * const arrayOfArgs);
I think "static" would not be sensible, for the same reason as making the
declarations of library functions say "static" would not be sensible.
Pedantically, implementations could be made to work despite this misleading
formality of syntax (after all, they already do so with "static" functions
anyway), but why bother?
> If I were calling it from, say, a POSIX.1 "exec..." call, I might
>prefer to use
> static int main(int numofArgs,
> const char * const * const arrayOfArgs);
Returning argc's type to int instead of size_t, but otherwise identical to
your previous suggestion? Your suggestions seem a bit incoherent.
> Of course, I might also want to use other variations:
> int main();
Allowed.
> static int main();
Disallowed.
> main();
Allowed.
> A quick read through Section 2.1.2.2.1 would seem to indicate that the
>only two acceptable prototypes are the two I listed above. Is this the case?
It is.
> Is there any way to express the "constness" configuration of the
>"arrayOfArgs" parameter using the more readable "[]" syntax instead of all
>those *'s?
In the paragraphs defining the meaning of the "const" qualifier, yes. But
again, if you try using such a declaration, then your program has undefined
behavior (though it is likely to work with most implementations).
> Are the proposed C++ rules regarding the "main" prototype different
>than the C rules established in American National Standard X3.159-1989?
The proposed rules in Ellis & Stroustrop are the same as for C. (This is
not necessarily the current answer.)
--
<< If this were the company's opinion, I would not be allowed to post it. >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will. Force = program size * destruction.
Every technical corrigendum is met by an equally troublesome new defect report.
Author: arthur@Smallworld.co.uk (Arthur Chance)
Date: 2 Sep 1993 14:02:54 GMT Raw View
In article <263gn7$2ui@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond)
writes:
> It might be sensible to make the argc parameter size_t instead of int, but
> I think it will be a long (:-) time before we see operating systems that
> permit passing more than 32767 strings in a command line, or invokers who
> wish to pass such.
egrep pattern `find /var/spool/news -type f -print`
We have ~200K news articles online, so argc would be _way_ above 32767.
This is 10% joke, 90% serious - I actually found myself trying to do this
a few days ago. Of course, it didn't work. :-}
Author: jfw@ksr.com (John F. Woods)
Date: 2 Sep 93 15:19:50 EDT Raw View
arthur@Smallworld.co.uk (Arthur Chance) writes:
>In article <263gn7$2ui@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond)
>writes:
>> It might be sensible to make the argc parameter size_t instead of int, but
>> I think it will be a long (:-) time before we see operating systems that
>> permit passing more than 32767 strings in a command line, or invokers who
>> wish to pass such.
>egrep pattern `find /var/spool/news -type f -print`
>We have ~200K news articles online, so argc would be _way_ above 32767.
>This is 10% joke, 90% serious - I actually found myself trying to do this
>a few days ago. Of course, it didn't work. :-}
Indeed, there are operating systems where there is no fixed limit on the size
of the argument list array, and on the system I run at home,
>egrep pattern `find /var/spool/news -type f -print`
would probably work (well, due to not having enough memory, it might have to
be "cd /var/spool/news ; egrep pattern `find . -type f -print`").
Just because the first argument to main() is "int" not "size_t" doesn't
mean that one can count on never seeing more than 32767 argument strings;
it merely means you can't count on using more than that if you want them.
That still doesn't excuse "int"/"size_t" colorblindness, of course, since
where I work, objects of type "size_t" can hold numbers as large as
18,446,744,073,709,551,615 (sizeof(size_t)*CHAR_BITS is left to the student
as an exercise :-).
Author: xtifr@netcom.com (Chris Waters)
Date: Fri, 3 Sep 1993 01:24:25 GMT Raw View
In <264uee$kpl@hydrogen.smallworld.co.uk> arthur@Smallworld.co.uk (Arthur Chance) writes:
>In article <263gn7$2ui@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond)
>writes:
>> It might be sensible to make the argc parameter size_t instead of int, but
>> I think it will be a long (:-) time before we see operating systems that
>> permit passing more than 32767 strings in a command line, or invokers who
>> wish to pass such.
>egrep pattern `find /var/spool/news -type f -print`
>We have ~200K news articles online, so argc would be _way_ above 32767.
>This is 10% joke, 90% serious - I actually found myself trying to do this
>a few days ago. Of course, it didn't work. :-}
Hmm, on any *reasonable* system, an int will hold approx +-2 billion,
so this shouldn't be an issue on most machines that *have* a
/var/spool/news directory. I don't see what relevance 32767 has to
ints! Except, perhaps on messy-DOG systems. :-)
(OTOH, with the command given above, the size of argv is more likely to
be a problem than the size of argc!)
--
Chris Waters | "By experimentation, I have found that if I stand still and
xtifr@netcom.COM| spin a universe around me, I get dizzy." -- W. Allison
Author: qbarnes@urbana.mcd.mot.com (Quentin Barnes)
Date: Thu, 2 Sep 1993 19:41:51 GMT Raw View
In <2637nb$h30@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
> American National Standard X3.159-1989, Section 2.1.2.2.1 ("Program
>Startup") says that each of these two prototypes is a permissible prototype for
>the C "main" function:
> int main(void);
> int main(int numOfArgs, char *arrayOfArgs[]);
[...]
While we're on the subject, does anyone know why argc is not "unsigned int"?
Is there ever a possibility of it being negative?
>+--------+ main() { const char c = 'c'; char *pc; const char **pcc = &pc;
>|John | *pcc = &c; *pc = 'C'; } // Whoops!
>|Davison | Disclaimer: The information contained in this article is not
>+--------+ representative of Northern Telecom and/or BNR.
--
Quentin Barnes qbarnes@urbana.mcd.mot.com Speaking for myself.
Author: diamond@jit.dec.com (Norman Diamond)
Date: 3 Sep 1993 07:31:48 GMT Raw View
In article <1993Sep2.194151.23027@urbana.mcd.mot.com> qbarnes@urbana.mcd.mot.com (Quentin Barnes) writes:
>While we're on the subject, does anyone know why argc is not "unsigned int"?
Maybe no one noticed before that this could be done without breaking any
code and without adding any further burden to making implementations conform.
>Is there ever a possibility of it being negative?
The standard guarantees that there is not.
--
<< If this were the company's opinion, I would not be allowed to post it. >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will. Force = program size * destruction.
Every technical corrigendum is met by an equally troublesome new defect report.
Author: lou@xilinx.com (Lou Sanchez-Chopitea)
Date: Fri, 3 Sep 1993 17:23:22 GMT Raw View
In article <2637nb$h30@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
>
> American National Standard X3.159-1989, Section 2.1.2.2.1 ("Program
>Startup") says that each of these two prototypes is a permissible prototype for
>the C "main" function:
>
[stuff deleted]
>
> If I'm not calling "main" recursively or using it in any other funny
>manner, I would prefer the following:
>
> static int main(size_t numofArgs,
------
> const char * const * const arrayOfArgs);
>
Can this actually work? How does the startup code get to the main entry
point if it is not exported? What does X3.159-1989 say about this?
[more deleted]
>--
>+--------+ main() { const char c = 'c'; char *pc; const char **pcc = &pc;
>|John | *pcc = &c; *pc = 'C'; } // Whoops!
>|Davison | Disclaimer: The information contained in this article is not
>+--------+ representative of Northern Telecom and/or BNR.
Cheers
Lou
--
Lou Sanchez-Chopitea EMail: lou@xilinx.com
Senior Software Engineer SnailMail: 2100 Logic Drive
SpeakMail: (408) 879-5059 San Jose, CA 95124
FaxMail: (408) 559-7114