is this stadard C?

  • Follow


I saw something recently for the first time:

   int main(int argc, char **argv, char **envp)
                                            ^
The thing I had never seen was a third arg to the main function. I 
thought main either took no args or 2 args. Is this not the case?

Lowell
0
Reply lkirsh (134) 2/22/2005 4:17:29 AM

Lowell Kirsh wrote:

> I saw something recently for the first time:
> 
>    int main(int argc, char **argv, char **envp)
>                                             ^
> The thing I had never seen was a third arg to the main function. I
> thought main either took no args or 2 args. Is this not the case?
> 
> Lowell

Its used for environment variables, which is a standard unix feature.

Subprocesses "inherit" the parents environment, and this can be used as a
simple interprocess communications mechanism.


gtoomey
www.gregorytoomey.com
0
Reply nospam258 (216) 2/22/2005 4:37:24 AM


Lowell Kirsh <lkirsh@cs.ubc.ca> writes:

> I saw something recently for the first time:
>
>    int main(int argc, char **argv, char **envp)
>                                             ^
> The thing I had never seen was a third arg to the main function. I
> thought main either took no args or 2 args. Is this not the case?

Yes, main() may only be portably defined with zero or two
parameters.  Some versions of Unix allow a third parameter for
main(), but this is not standard even among Unix variants.
-- 
"I should killfile you where you stand, worthless human." --Kaz
0
Reply blp (3953) 2/22/2005 4:37:40 AM

Lowell Kirsh wrote:

> I saw something recently for the first time:
> 
>   int main(int argc, char **argv, char **envp)
>                                            ^
> The thing I had never seen was a third arg to the main function.
> I thought main either took no args or 2 args.
> Is this not the case?

         > cat main.c
         int main(int argc) {
           return 0;
           }

         > gcc -Wall -std=c99 -pedantic -o main main.c
         main.c:1: warning: 'main' takes only zero or two arguments
         > vi main.c
         > cat main.c
         int main(int argc, float x) {
           return 0;
           }

         > gcc -Wall -std=c99 -pedantic -o main main.c
         main.c:1: warning: second argument of 'main' should be 'char **'
         > vi main.c
         > cat main.c
         int main(int argc, char* argv[], float x) {
           return 0;
           }

         > gcc -Wall -std=c99 -pedantic -o main main.c
         main.c:1: warning: third argument of 'main' should probably be 
'char **'
         > vi main.c
         > cat main.c
         int main(int argc, char* argv[], char* envp[], float x) {
           return 0;
           }

         > gcc -Wall -std=c99 -pedantic -o main main.c
         main.c:1: warning: 'main' takes only zero or two arguments
0
Reply E.Robert.Tisdale (2031) 2/22/2005 4:38:20 AM

In article <cvebop$4gp$1@mughi.cs.ubc.ca>,
Lowell Kirsh  <lkirsh@cs.ubc.ca> wrote:
>I saw something recently for the first time:
>
>   int main(int argc, char **argv, char **envp)
>                                            ^
>The thing I had never seen was a third arg to the main function. I 
>thought main either took no args or 2 args. Is this not the case?

This is the case for strictly conforming programs compiled under a
hosted implementation.

A platform can let you define main any way it wants to let you,
since defining it in any way other than
    int main(void)
or
    int main(int argc,char **argv)
frees the compiler from the requirements placed on it by the standard
(in standardese, it invokes undefined behavior), so it can do anything
(including, as the most frequent case, almost what it would have done
if you'd used the correct definition).
C99 attempted to legitimize this by saying that, in addition to the two
standard definitions of main, it can also be defined in "some other
implementation-defined manner"; this really doesn't change anything,
though - you're still stepping outside the language it defines if you
have a main() that returns anything other than int or takes anything
other than no arguments or the two specified by the standard.

In this particular case, a third pointer as an argument to main is a
(somewhat archaic) unixism that points to a collection of environment
variables.  The standard-conforming way to get at these is to use
getenv(), and POSIX also gives you putenv() to set them (I'm not sure
if that's possible through the envp pointer).


dave

-- 
Dave Vandervies                               dj3vande@csclub.uwaterloo.ca
I suppose automatic updates will also install the additional memory I need
to get reasonable performance.
                                                --Alex Colvin in comp.arch
0
Reply dj3vande (656) 2/22/2005 4:38:49 AM

Lowell Kirsh wrote:

> I saw something recently for the first time:
> 
>   int main(int argc, char **argv, char **envp)

         > cat main.c
         #include <stdio.h>

         int main(int argc, char* argv[], char* envp[]) {
           size_t        j = 0;
           while (NULL != envp[j])
             fprintf(stdout, "%s\n", envp[j++]);
           return 0;
           }

         > gcc -Wall -std=c99 -pedantic -o main main.c
         > ./main
             .
             .
             .
         OSTYPE=linux
         VENDOR=intel
         MACHTYPE=i386
             .
             .
             .

         > man getenv
         GETENV(3)         Linux Programmer�s Manual         GETENV(3)



         NAME
               getenv - get an environment variable

         SYNOPSIS
               #include <stdlib.h>

               char *getenv(const char **name);

         DESCRIPTION
               The getenv() function searches the environment list
               for a string that matches the string pointed to by name.
               The strings are of the form name=value.

         RETURN VALUE
               The getenv() function returns a pointer to the value
               in the environment, or NULL if there is no match.

         CONFORMING TO
               SVID 3, POSIX, BSD 4.3, ISO 9899

         SEE ALSO
               putenv(3), setenv(3), clearenv(3), unsetenv(3), environ(5)



         GNU                       1993-04-03                GETENV(3)
0
Reply E.Robert.Tisdale (2031) 2/22/2005 5:13:32 AM

Thank you all for your answers. I get the impression that using this 
form is pretty unnecessary. It seems like using getenv would be a better 
solution in most cases.

Lowell

Lowell Kirsh wrote:
> I saw something recently for the first time:
> 
>   int main(int argc, char **argv, char **envp)
>                                            ^
> The thing I had never seen was a third arg to the main function. I 
> thought main either took no args or 2 args. Is this not the case?
> 
> Lowell
0
Reply lkirsh (134) 2/22/2005 10:19:57 AM

In article <877jl1ciqz.fsf@benpfaff.org>,
Ben Pfaff  <blp@cs.stanford.edu> wrote:

>Yes, main() may only be portably defined with zero or two
>parameters.  Some versions of Unix allow a third parameter for
>main(), but this is not standard even among Unix variants.

I find that hard to believe.  What unix does it not work on?

-- Richard
0
Reply richard91 (3683) 2/22/2005 2:26:50 PM

On Tue, 22 Feb 2005 02:19:57 -0800, Lowell Kirsh <lkirsh@cs.ubc.ca>
wrote:

>Thank you all for your answers. I get the impression that using this 
>form is pretty unnecessary. It seems like using getenv would be a better 
>solution in most cases.
>
If you know the name of the environment variable you're looking for,
yes, it's easier to use getenv(). If, for some reason, you wanted to
search the environment variables, the "char *env[]" form would be the
way to do it.

>Lowell
>
>Lowell Kirsh wrote:
>> I saw something recently for the first time:
>> 
>>   int main(int argc, char **argv, char **envp)
>>                                            ^
>> The thing I had never seen was a third arg to the main function. I 
>> thought main either took no args or 2 args. Is this not the case?
>> 
>> Lowell

-- 
Al Balmer
Balmer Consulting
removebalmerconsultingthis@att.net
0
Reply albalmer (2299) 2/22/2005 3:38:40 PM

richard@cogsci.ed.ac.uk (Richard Tobin) writes:

> In article <877jl1ciqz.fsf@benpfaff.org>,
> Ben Pfaff  <blp@cs.stanford.edu> wrote:
>
>>Yes, main() may only be portably defined with zero or two
>>parameters.  Some versions of Unix allow a third parameter for
>>main(), but this is not standard even among Unix variants.
>
> I find that hard to believe.  What unix does it not work on?

It does not matter where it works or not.  It is not standard
because it is not in SuSv3 or other modern Unix standards.
-- 
"...deficient support can be a virtue.
 It keeps the amateurs off."
--Bjarne Stroustrup
0
Reply blp (3953) 2/22/2005 4:48:57 PM

Alan Balmer <albalmer@att.net> writes:
> On Tue, 22 Feb 2005 02:19:57 -0800, Lowell Kirsh <lkirsh@cs.ubc.ca>
> wrote:
>
>>Thank you all for your answers. I get the impression that using this 
>>form is pretty unnecessary. It seems like using getenv would be a better 
>>solution in most cases.
>>
> If you know the name of the environment variable you're looking for,
> yes, it's easier to use getenv(). If, for some reason, you wanted to
> search the environment variables, the "char *env[]" form would be the
> way to do it.

<OT>
Passing the extra parameter to main() is one way to do it.  Another is
(I think) declaring "extern char *environ[];".  The latter is cleaner,
IMHO.  Both, of course, are non-standard.
</OT>

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21545) 2/22/2005 8:25:42 PM

Keith Thompson wrote:

> Passing the extra parameter to main() is one way to do it.
> Another is (I think) declaring "extern char *environ[];".
> The latter is cleaner, IMHO.
> Both, of course, are non-standard.

getenv(const char *) *is* standard
but you must know the environment variable name
that you are looking for.
0
Reply E.Robert.Tisdale (2031) 2/22/2005 8:46:25 PM

"E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> writes:
> Keith Thompson wrote:
>
>> Passing the extra parameter to main() is one way to do it.
>> Another is (I think) declaring "extern char *environ[];".
>> The latter is cleaner, IMHO.
>> Both, of course, are non-standard.
>
> getenv(const char *) *is* standard
> but you must know the environment variable name
> that you are looking for.

Yes, thank you for restating the obvious.  In Alan Balmer's previous
article, to which I was responding, he wrote (and I quoted):

] If you know the name of the environment variable you're looking for,
] yes, it's easier to use getenv(). If, for some reason, you wanted to
] search the environment variables, the "char *env[]" form would be
] the way to do it.

You also snipped the "<OT>" and "</OT>" tags I had placed around my
comments.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://users.sdsc.edu/~kst>
We must do something.  This is something.  Therefore, we must do this.
0
Reply kst-u (21545) 2/22/2005 9:47:28 PM

On Tue, 22 Feb 2005 08:38:40 -0700,
    Alan Balmer <albalmer@att.net> wrote:


> If you know the name of the environment variable you're looking for,
> yes, it's easier to use getenv(). If, for some reason, you wanted to
> search the environment variables, the "char *env[]" form would be the
> way to do it.
>

If you realy want to do that then use the global variable environ.
The third paramter passed to main in unix won't stay valid after
you have modified the environment.  So even on unix it is better
to pretend that the third argument to main doesn't exist.  The
ANSI C standard doesn't, however, provide any standard for changing the
environment, let alone the existense or non-existence of the environ
global variable.

Villy
0
Reply vek (278) 2/23/2005 8:40:26 AM

Villy Kruse wrote:
> 
> On Tue, 22 Feb 2005 08:38:40 -0700,
>     Alan Balmer <albalmer@att.net> wrote:
> 
> > If you know the name of the environment variable you're looking for,
> > yes, it's easier to use getenv(). If, for some reason, you wanted to
> > search the environment variables, the "char *env[]" form would be the
> > way to do it.
> >
> 
> If you realy want to do that then use the global variable environ.

Not if you want your code to stay portable.

> The third paramter passed to main in unix won't stay valid after
> you have modified the environment.  So even on unix it is better
> to pretend that the third argument to main doesn't exist.  The
> ANSI C standard doesn't, however, provide any standard for changing the
> environment, let alone the existense or non-existence of the environ
> global variable.

Precisely.
0
Reply infobahn (503) 2/23/2005 9:08:30 AM

On Wed, 23 Feb 2005 12:25:53 +0000,
    Lawrence Kirby <lknews@netactive.co.uk> wrote:


> On Wed, 23 Feb 2005 09:08:30 +0000, infobahn wrote:
>
>> Villy Kruse wrote:
>>> 
>>> On Tue, 22 Feb 2005 08:38:40 -0700,
>>>     Alan Balmer <albalmer@att.net> wrote:
>>> 
>>> > If you know the name of the environment variable you're looking for,
>>> > yes, it's easier to use getenv(). If, for some reason, you wanted to
>>> > search the environment variables, the "char *env[]" form would be the
>>> > way to do it.
>>> >
>>> 
>>> If you realy want to do that then use the global variable environ.
>> 
>> Not if you want your code to stay portable.
>
> Using either method (environ or 3 argument main) makes your code
> non-portable as far as standard C is concerned. extern char **environ is
> at least defined by POSIX and as such would have to be considered more
> portable. Using the 3 argument form of main() will probably compile and
> link successfully on more platforms, it just means that where it isn't
> supported it misbehaves at runtime rather than fails to compile, which is
> worse.
>

I was trying to point out that even on systems where it actualy does
work it may stop working for no appearent reason.  That means that even
in cases where porting is not an issue, and even if some test programs
has proven it works on a particular system, using the third argument to
main may fail.

Villy
0
Reply vek (278) 2/23/2005 12:23:43 PM

On Wed, 23 Feb 2005 09:08:30 +0000, infobahn wrote:

> Villy Kruse wrote:
>> 
>> On Tue, 22 Feb 2005 08:38:40 -0700,
>>     Alan Balmer <albalmer@att.net> wrote:
>> 
>> > If you know the name of the environment variable you're looking for,
>> > yes, it's easier to use getenv(). If, for some reason, you wanted to
>> > search the environment variables, the "char *env[]" form would be the
>> > way to do it.
>> >
>> 
>> If you realy want to do that then use the global variable environ.
> 
> Not if you want your code to stay portable.

Using either method (environ or 3 argument main) makes your code
non-portable as far as standard C is concerned. extern char **environ is
at least defined by POSIX and as such would have to be considered more
portable. Using the 3 argument form of main() will probably compile and
link successfully on more platforms, it just means that where it isn't
supported it misbehaves at runtime rather than fails to compile, which is
worse.

>> The third paramter passed to main in unix won't stay valid after
>> you have modified the environment.  So even on unix it is better
>> to pretend that the third argument to main doesn't exist.  The
>> ANSI C standard doesn't, however, provide any standard for changing the
>> environment, let alone the existense or non-existence of the environ
>> global variable.
>
>Precisely.

getenv() is the portable way to get environment strings. But if you need
more than it can offer, environ is a better bet than 3 argument main.
While both are outside the scope of standard C I think it is worth
stressing that 3 argument main should be treated as nothing more than a
historical curiosity now.

Lawrence
0
Reply lknews (877) 2/23/2005 12:25:53 PM

Lawrence Kirby wrote:
> 
> On Wed, 23 Feb 2005 09:08:30 +0000, infobahn wrote:
> 
> > Villy Kruse wrote:
> >>
> >> On Tue, 22 Feb 2005 08:38:40 -0700,
> >>     Alan Balmer <albalmer@att.net> wrote:
> >>
> >> > If you know the name of the environment variable you're looking for,
> >> > yes, it's easier to use getenv(). If, for some reason, you wanted to
> >> > search the environment variables, the "char *env[]" form would be the
> >> > way to do it.
> >> >
> >>
> >> If you realy want to do that then use the global variable environ.
> >
> > Not if you want your code to stay portable.
> 
> Using either method (environ or 3 argument main) makes your code
> non-portable as far as standard C is concerned.

Yes, precisely.

> extern char **environ is
> at least defined by POSIX and as such would have to be considered more
> portable.

More portable, but not maximally portable. environ doesn't provide
to an otherwise portable program anything that getenv() can't provide
portably; that is, if the program needs to enquire the environment,
getenv() is perfectly adequate to the task, and doesn't rely on
the existence of environ.


<snipped good stuff that I agree with>
0
Reply infobahn (503) 2/23/2005 3:42:40 PM

In article <421CA439.2BD10CBF@btinternet.com>,
infobahn  <infobahn@btinternet.com> wrote:
>Lawrence Kirby wrote:

>> extern char **environ is
>> at least defined by POSIX and as such would have to be considered more
>> portable.
>
>More portable, but not maximally portable. environ doesn't provide
>to an otherwise portable program anything that getenv() can't provide
>portably; that is, if the program needs to enquire the environment,
>getenv() is perfectly adequate to the task, and doesn't rely on
>the existence of environ.

If a program wants to make a list of all the environment variables that
are defined, can it do so using getenv() and still finish before the
heat death of the universe?


dave

-- 
Dave Vandervies                            dj3vande@csclub.uwaterloo.ca
Fortunately programmers who actually use those anomalous cases are few,
and getting fewer every time we catch up to one.
                                        --David Thompson in comp.lang.c
0
Reply dj3vande (656) 2/23/2005 4:46:01 PM

Dave Vandervies wrote:
> 
> In article <421CA439.2BD10CBF@btinternet.com>,
> infobahn  <infobahn@btinternet.com> wrote:
> >[...]if the program needs to enquire the environment,
> >getenv() is perfectly adequate to the task, and doesn't rely on
> >the existence of environ.
> 
> If a program wants to make a list of all the environment variables that
> are defined, can it do so using getenv() and still finish before the
> heat death of the universe?

Sure. Just run it on a quantum computer. :-)
0
Reply infobahn (503) 2/23/2005 5:14:59 PM

On Wed, 23 Feb 2005 12:25:53 +0000, Lawrence Kirby
<lknews@netactive.co.uk> wrote:

>extern char **environ is
>at least defined by POSIX and as such would have to be considered more
>portable.

I'm glad you mentioned that - I hadn't realized it was defined by
POSIX (though I've now looked it up :-). I'll remember that just in
case I ever need to use it. (Which seems unlikely, actually.)

-- 
Al Balmer
Balmer Consulting
removebalmerconsultingthis@att.net
0
Reply albalmer (2299) 2/23/2005 5:51:11 PM

20 Replies
33 Views

(page loaded in 0.22 seconds)


Reply: