is this stadard C?

L

Lowell Kirsh

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
 
G

Gregory Toomey

Lowell said:
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
 
B

Ben Pfaff

Lowell Kirsh said:
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.
 
E

E. Robert Tisdale

Lowell said:
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
 
D

Dave Vandervies

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
 
E

E. Robert Tisdale

Lowell said:
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)
 
L

Lowell Kirsh

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
 
R

Richard Tobin

Ben Pfaff said:
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
 
A

Alan Balmer

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.
 
B

Ben Pfaff

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.
 
K

Keith Thompson

Alan Balmer said:
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>
 
E

E. Robert Tisdale

Keith said:
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.
 
K

Keith Thompson

E. Robert Tisdale said:
Keith said:
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.
 
V

Villy Kruse

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
 
I

infobahn

Villy said:
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.
 
V

Villy Kruse

Villy said:
On Tue, 22 Feb 2005 08:38:40 -0700,

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
 
L

Lawrence Kirby

Villy said:
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.
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
 
I

infobahn

Lawrence said:
Villy said:
On Tue, 22 Feb 2005 08:38:40 -0700,

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>
 
D

Dave Vandervies

Lawrence Kirby wrote:

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
 
I

infobahn

Dave said:
[...]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. :)
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,881
Members
47,418
Latest member
NoellaXku

Latest Threads

Top