main函数的第三个参数envp

main函数两种常见形式

在C/C++ 程序中, 操作系统通过main函数来调用程序,main函数是从程序的入口。常见的main 函数定义有如下两种方式:

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

第一种方式main 不接受参数,第二种方式可以在通过shell调用程序时给main 函数传入参数,argc 表示参数的个数,argv 为参数的内容

举例说明, main 函数以第二种方式定义, 程序名为test,在shell (bash for linux ,powershell for windows)中运行该程序:

test p

则argc = 2 , 两个参数, 其中程序名固定为第一个参数,在本例中 argv[0] = test , argv[1] = p

bash 中各种命令不同的参数不同的效果可以通过这种机制实现

main的第三种形式

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

第三个参数用来在程序运行时获取系统的环境变量,操作系统运行程序时通过envp 参数将系统环境变量传递给程序

测试代码:

#include<iostream>


int main(int agrc,char * argv[],char * envp[])
{

    std::cout <<"Test the envp parameter of main function"<<std::endl;
    std::cout << "environment paramter of system: "<<std::endl;

    for(int i  = 0 ;  envp[i] ; ++i)
    {
        std::cout<<envp[i]<<std::endl;
    }
    return 0;

}

程序运行后将系统所有环境变量打印出来了(如下给出的是windows上测试结果,linux 上环境变量与windows上不同):

Test the envp parameter of main function
environment paramter of system:
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\alpha\AppData\Roaming
asl.log=Destination=file
CommonProgramFiles=C:\Program Files (x86)\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=DELL
ComSpec=C:\Windows\system32\cmd.exe
FP_NO_HOST_CHECK=NO
GOPATH=D:\projects\go_project
GOROOT=D:\Go\
HOMEDRIVE=C:
HOMEPATH=\Users\alpha
LOCALAPPDATA=C:\Users\alpha\AppData\Local
LOGONSERVER=\MicrosoftAccount
NUMBER_OF_PROCESSORS=4
OS=Windows_NT
Path=D:\Python27\;D:\Python27\Scripts;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32\config\systemprofile.dnx\bin;C:\Program Files\Microsoft DNX\Dnvm\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;D:\Go\bin;D:\Program Files\nodejs\;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Users\alpha\AppData\Roaming\npm;E:\Program Files\phantomjs-2.1.1-windows\phantomjs-2.1.1-windows\bin
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_ARCHITEW6432=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 60 Stepping 3, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=3c03
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files (x86)
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PSModulePath=C:\Users\alpha\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
PUBLIC=C:\Users\Public
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=C:\Users\alpha\AppData\Local\Temp
TMP=C:\Users\alpha\AppData\Local\Temp
USERDOMAIN=DELL
USERDOMAIN_ROAMINGPROFILE=DELL
USERNAME=alpha
USERPROFILE=C:\Users\alpha
VS140COMNTOOLS=D:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
windir=C:\Windows

是否该使用三个参数的main函数

先说结论:应该尽量避免使用

有一篇environ 的文章把原因说的比较清楚:

Because ISO C specifies that the main function be written
with two arguments, and because this third argument provides
no benefit over the global variable environ, POSIX.1 specifies
that environ should be used instead of the (possible) third
argument. Access to specific environment variables is
normally through the getenv and putenv functions instead of
through the environ variable. But to go through the entire
environment, the environ pointer must be used

ISO C/ISO C++ ,POSIX 标准都不支持main 三个参数的定义形式,VC 和GNU编译器都扩展了main 函数的定义,所以目前可以这样使用。
如果要编写更加可移植的程序,应该使用全局环境变量environ 来代替envp的作用,如果要访问特定的环境变量,应该使用getenv 和putenv 函数

#include<iostream>
#include<stdlib.h>

extern char** environ;

int main(int agrc,char * argv[])
{

    std::cout <<"Test the envp parameter of main function"<<std::endl;
    std::cout << "environment paramter of system: "<<std::endl;

    char ** env = environ;
    while(*env)
    {
        std::cout<<*env<<std::endl;
    }
    return 0;

}

运行效果与使用envp参数一样。

getenv 和putenv 也是定义在stdlib.h 中,函数原型如下:

int putenv(char str);
int setenv(const char
name, const char *value, int rewrite);