8

I have come to understand that char **envp is the third argument to main, and with the help of the code below, I was able to see what it actually contains.

int main(int argc, char *argv[], char *env[])
{
  int i;
  for (i=0 ; env[i] ; i++)
    std::cout << env[i] << std::endl;
  std::cout << std::endl;
}

My question is: why (in what situations) would programmers need to use this? I have found many explanations for what this argument does, but nothing that would tell me where this is typically used. Trying to understand what kind of real world situations this might be used in.

Lucas
  • 523
  • 2
  • 10
  • 20
aspen100
  • 965
  • 11
  • 22
  • 3
    This is old, early Unix before POSIX. Apple CRTs even pass a 4th argument. You don't need it anymore, getenv() is standard since C89. – Hans Passant Oct 05 '13 at 15:08
  • 4
    @HansPassant: Although `getenv()` allows you to find the value of an environment variable you know about, it does not allow you to find the value of an environment variable whose name you don't know. The `envp` argument to `main()` and the `environ` global variable allow you to find all the environment variables. Thus, `getenv()` on its own is not a replacement for the `envp` argument. – Jonathan Leffler Oct 05 '13 at 15:22
  • Closely related to, but slightly different from, [What should `main()` return in C and C++?](http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c) Also of interest is [Is `char *envp[]` as a third argument to `main()` portable?](http://stackoverflow.com/questions/10321435/is-char-envp-as-a-third-argument-to-main-portable) – Jonathan Leffler Oct 05 '13 at 15:26
  • Wow, I didn't know this feature of C/C++ ! In retrospect, I was able to find it here http://en.cppreference.com/w/cpp/language/main_function (3). – alfC Feb 16 '18 at 10:30
  • Also from http://en.cppreference.com/w/cpp/utility/program/getenv, the global variable `char** environ` has the same information. "On POSIX systems, the environment variables are also accessible through the global variable environ, declared as extern char **environ; in , and through the optional third argument, envp, of the main function." – alfC Feb 16 '18 at 10:42

4 Answers4

11

It is an array containing all the environmental variables. It can be used for example to get the user name or home directory of current logged in user. One situation is, for example, if I want to hold a configuration file in user's home directory and I need to get the PATH;

int main(int argc, char* argv[], char* env[]){

std::cout << env[11] << '\n';  //this prints home directory of current user(11th for me was the home directory)

return 0;
}

Equivalent of env is char* getenv (const char* name) function which is easier to use, for example:

 std::cout << getenv("USER");

prints user name of current user.

khajvah
  • 4,889
  • 9
  • 41
  • 63
  • 1
    @srihari I don't understand, why would you need access for user's password? There is not `environmental variable` that holds user's password. – khajvah Oct 05 '13 at 21:38
  • Wow, I didn't know this feature of C/C++ ! To be honest, for some reason I find this approach of `main` with three arguments more elegant than using `getenv`. Specially because it gives a concrete scope to the environment variables that is not global. – alfC Feb 16 '18 at 10:32
  • @alfC envs are global per process by nature, so it's fine to use as global. Of course you can misuse `getenv` by using it randomly everywhere but that's not its problem really :). – khajvah Feb 16 '18 at 10:42
  • Well, yes, but for example program arguments (`argc` and `argv`) are not global, and environment variables are global (because of `getenv`). I always found this inconsistent. Also another difference between `getenv` and `env` seems to be that to use `getenv` you need to know the name of the variable exactly. With `env` you can list all the variables (and look for a pattern for example). One of the comments says it is "old", is it? Now that I know it exists I really would use to pass to "named" arguments to small C++ programs without bothering parsing `argc` and `argv`. – alfC Feb 16 '18 at 10:48
  • 1
    @alfC It's not about old and new. As far as I know only `getenv` is part of the C standard, so that's why people advise not to use `envp`. https://stackoverflow.com/a/10321474/1527217 – khajvah Feb 16 '18 at 12:05
  • do you mean that if you need environment variables it would be a bit "more" standard to use main with three arguments than getenv? – alfC Feb 16 '18 at 16:02
  • 2
    @alfC the other way around. `getenv` is the standard way, defined by C standard. – khajvah Feb 21 '18 at 12:20
8

The getenv() function allows you to find the value of a specific environment variable, but doesn't provide a mechanism to scan over the entire list of environment variables. The envp argument allows you to iterate over the entire list of environment variables, as your demonstration code shows which is simply not feasible using the getenv() interface.

On POSIX systems, there is a global variable, extern char **environ;, which also points to the environment. The functions putenv() (ancient, non-preferred because it presents memory management problems), setenv() and unsetenv() can also manipulate the environment variable list (as defined by environ). A program can directly modify environ or the values it points at, but that is not advisable.

If you are using fork() and the exec*() family of functions, unless you use execve() and specify the environment explicitly, the child process will receive the environment defined by environ.

No header declares environ — AFAIK, it is the only variable defined by POSIX without a header to declare it. The C standard recognizes the int main(int argc, char **argv, char **envp) signature for main() as a common extension to the standard, documented in Annex J.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

This is typically used to set configuration options or other information for a whole group of programs. Another use is to specify environment settings for a particular machine or user setup.
Well known examples are the PATH variable that contains the lookup pathes for executables, or the LD_LIBRARY_PATH variable that contains the pathes where to lookup the shared libraries.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

env allows you to access the environment variables. It contains an array of strings. Examples are the users home directory, the configured language scheme, the PATH variable (where to look for directly executable programs?), ...

You can also set individual environment variables. For example, if you have testing (learning) and also a production system you deploy your application to. On one system you could set the variable "MY_APP_MODE=TEST" and on the other system you could specify "MY_APP_MODE=PROD". So you don't need to deploy different applications to the test and production systems. Your application could determine itself in what environment it is run.

MrSnrub
  • 1,123
  • 1
  • 11
  • 19