473,402 Members | 2,061 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,402 software developers and data experts.

is this stadard C?

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
Nov 14 '05 #1
20 1218
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
Nov 14 '05 #2
In article <cv**********@mughi.cs.ubc.ca>,
Lowell Kirsh <lk****@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 dj******@csclub.uwaterloo.ca
I suppose automatic updates will also install the additional memory I need
to get reasonable performance.
--Alex Colvin in comp.arch
Nov 14 '05 #3
Lowell Kirsh <lk****@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
Nov 14 '05 #4
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
Nov 14 '05 #5
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

Nov 14 '05 #6
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

Nov 14 '05 #7
In article <87************@benpfaff.org>,
Ben Pfaff <bl*@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
Nov 14 '05 #8
On Tue, 22 Feb 2005 02:19:57 -0800, Lowell Kirsh <lk****@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
re************************@att.net
Nov 14 '05 #9
ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <87************@benpfaff.org>,
Ben Pfaff <bl*@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
Nov 14 '05 #10
Alan Balmer <al******@att.net> writes:
On Tue, 22 Feb 2005 02:19:57 -0800, Lowell Kirsh <lk****@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) ks***@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.
Nov 14 '05 #11
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.
Nov 14 '05 #12
"E. Robert Tisdale" <E.**************@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) ks***@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.
Nov 14 '05 #13
On Tue, 22 Feb 2005 08:38:40 -0700,
Alan Balmer <al******@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
Nov 14 '05 #14
Villy Kruse wrote:

On Tue, 22 Feb 2005 08:38:40 -0700,
Alan Balmer <al******@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.
Nov 14 '05 #15
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 <al******@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
Nov 14 '05 #16
On Wed, 23 Feb 2005 12:25:53 +0000,
Lawrence Kirby <lk****@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 <al******@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
Nov 14 '05 #17
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 <al******@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>
Nov 14 '05 #18
In article <42***************@btinternet.com>,
infobahn <in******@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 dj******@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
Nov 14 '05 #19
Dave Vandervies wrote:

In article <42***************@btinternet.com>,
infobahn <in******@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. :-)
Nov 14 '05 #20
On Wed, 23 Feb 2005 12:25:53 +0000, Lawrence Kirby
<lk****@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
re************************@att.net
Nov 14 '05 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Conrad | last post by:
Greetings, I have a need to print from Win98SE to a little serial label printer provided by United Parcel, so based on Mark Hammond's recommendation in 'Programming on Win32' I decided to try...
12
by: Nitin Manoharan | last post by:
Hello, How can I convert an int to a *char (best way please) I know a few round about methods myself :) Thank you
1
by: Chris B | last post by:
Does anyone know of a way in VB.net, to implement the following functionality in printing address labels. Allowing the user to select from which location on a stadard address label sheet (Avery...
0
by: RiteshDotNet | last post by:
I have develop a window service in vb.net in window service, i am running executeing exe which is reside on same system its gives error while running that exe file I am pasting error below "...
1
by: skinnay | last post by:
i have a program that has two parts, the first part populates a list with a loop and cin.getline(). the second part is a command prompt to manipulate the list. i have the first part done, and can...
1
by: Jenny | last post by:
Hi, Can I create an array of tags by assigning same name to these tags? For example, I have two <p> tags with the same name t1. But document.all.b.value=document.all.t.length does not...
7
by: alex.mizrahi | last post by:
helo i'm going to use pointers to member function with virtual inheritance in following way: struct base { public: typedef void (base::*fun_t)(void); int i; void call(fun_t f) {
9
by: kernelxu | last post by:
hi, everyone. now, I'am confused on such a problem: function setbuf(stdin, NULL) or setvbuf(stdin, NULL, _IONBF, 0) can set the stadard input stream unbuffered. however, why does my program...
0
by: cameron | last post by:
This is probably off topic, so please feel free to redirect me to proper news group, I am wondering if you can enable the XML comments in Visual Studio for other file types. I have written a...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.