Is char *envp[] as a third argument to main() portable

57,842

Solution 1

The function getenv is the only one specified by the C standard. The function putenv, and the extern environ are POSIX-specific.

EDIT

The main parameter envp is not specified by POSIX but is widely supported.

An alternative method of accessing the environment list is to declare a third argument to the main() function:

int main(int argc, char *argv[], char *envp[])

This argument can then be treated in the same way as environ, with the difference that its scope is local to main(). Although this feature is widely implemented on UNIX systems, its use should be avoided since, in addition to the scope limitation, it is not specified in SUSv3.

Solution 2

It isn't portable. *envp[] is a traditional UNIX thing, and not all modern UNIX systems implement it.

Also as a side note you could access envp by doing a pointer traversal over *argv[], overflowing it...but i don't think that can be considered safe programming. If you take a look at the process memory map you will see that envp[] is just above argv[].

Solution 3

The Standard describes two formats for main (see 5.1.2.2.1 in the C99 Standard (pdf))

a) int main(void)

and

b) int main(int argc, char **argv) or equivalent

and it allows implementations to define other formats (which can allow a 3rd argument)

c) or in some other implementation-defined manner.

Solution 4

The 3rd argument is valid in Microsoft C and GNU GCC:

Visual Studio 2015: Arguments to main

GNU C Programming Tutorial: Environment variables

Share:
57,842
Sangeeth Saravanaraj
Author by

Sangeeth Saravanaraj

An enthusiastic programmer!

Updated on July 15, 2022

Comments

  • Sangeeth Saravanaraj
    Sangeeth Saravanaraj almost 2 years

    In order to get an environment variable in a C program, one could use the following:

    • getenv()
    • extern char **environ;

    But other than the above mentioned, is using char *envp[] as a third argument to main() to get the environment variables considered part of the standard?

    #include <stdio.h>
    
    int main(int argc, char *argv[], char *envp[])
    {
        while(*envp)
            printf("%s\n",*envp++);
    }
    

    Is char *envp[] portable?

  • Daniel Fischer
    Daniel Fischer about 12 years
    An implementation may provide further formats for main, but these two are the only ones guaranteed to be present in any hosted implementation.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE about 12 years
    And you can go past the environment too and examine auxv... ;-)
  • skyel
    skyel about 12 years
    What is usually stored in auxv, because i was just wondering the other days why where the fields after envp constant(between runs)?
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE about 12 years
    Look in elf.h for the macros beginning with AT_. Some of the more interesting things are AT_SECURE, AT_RANDOM, AT_EXECFN, AT_HWCAP, and the uid/gid ones. Otherwise they're mostly of interest to the dynamic linker and libc init code. The format of auxv is pairs of system-word-size integers, the first of which is one of the AT_ constants (a tag) and the second of which is the value associated with that tag (possibly a pointer, depending on the tag).
  • Jonathan Leffler
    Jonathan Leffler about 10 years
    Note that the C standard recognizes this as a common alternative — even C89 mentioned it in Annex G (Portability Issues); it is in Annex J (Portability Issues) in both C99 and C11.
  • Braden Best
    Braden Best over 8 years
    What about using a pointer to find the end of argv, and going one step further? char **find = argv, **envp; while(*find) find++; envp = find + 1; Probably undefined behavior since an OS isn't guaranteed to put environment stuff after argv's last arg...
  • ben
    ben over 3 years
    It does not work with (at least) z/OS 2.4 and xlc/c99/c89 on the IBM Mainframe. There is a POSIX solution.
  • mtraceur
    mtraceur over 2 years
    More traditional/idiomatic and concise version of the last comment's way: char **envp = argv; while(*envp++);