Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取进程的argc和argv的替代方法_C++_Linux_Windows_Posix_Bsd - Fatal编程技术网

C++ 获取进程的argc和argv的替代方法

C++ 获取进程的argc和argv的替代方法,c++,linux,windows,posix,bsd,C++,Linux,Windows,Posix,Bsd,我正在寻找其他方法来获取提供给进程的命令行参数argc和argv,而无需直接访问传递到main()的变量 我想创建一个独立于main()的类,这样argc和argv就不必显式地传递给使用它们的代码 编辑:一些澄清似乎是正确的。我有这门课 class Application { int const argc_; char const** const argv_; public: explicit Application(int, char const*[]); }; Applica

我正在寻找其他方法来获取提供给进程的命令行参数
argc
argv
,而无需直接访问传递到
main()
的变量

我想创建一个独立于
main()
的类,这样
argc
argv
就不必显式地传递给使用它们的代码

编辑:一些澄清似乎是正确的。我有这门课

class Application
{
  int const argc_;
  char const** const argv_;

public:
  explicit Application(int, char const*[]);
};

Application::Application(int const argc, char const* argv[]) :
  argc_(argc),
  argv_(argv)
{
}

但是我想要一个默认构造函数
Application::Application()
,带有一些(很可能)C代码,从某处提取
argc
argv

要部分回答关于Windows的问题,可以通过返回
GetCommandLine
函数来获取命令行,它是有文档记录的,没有显式访问
main
函数的参数。

main
的参数是由C运行时定义的,也是获取命令行参数的唯一标准/可移植方法。不要与体制对抗。:)

如果您只想使用自己的API在程序的其他部分提供对命令行参数的访问,那么有很多方法可以做到这一点。只需在
main
中使用
argv/argc
初始化自定义类,从那时起,您可以忽略它们并使用自己的API。单例模式非常适合这种情况

说明,最流行的C++框架之一,Qt使用这种机制:

int main(int argc, char* argv[])
{
    QCoreApplication app(argc, argv);

    std::cout << app.arguments().at(0) << std::endl;

    return app.exec();
}
然后,使用属性的应用程序中的任何位置都可以使用参数

我注意到在您更新的问题中,您的类在其实例中直接存储了
argc/argv
的副本:

int const argc_;
char const** const argv_;
虽然这应该是安全的(argv
argv
指针的生命周期应该在进程的整个生命周期内都是有效的),但它不是很像C++。考虑创建一个字符串向量(<代码> STD::vector < /代码>)作为容器并复制字符串。然后,它们甚至可以安全地可变(如果您愿意的话!)

我想创建一个独立于main()的类,这样就不必显式地将argc和argv传递给使用它们的代码

不清楚为什么从
main
传递此信息是一件必须避免的坏事。主要框架就是这样做的

我建议您考虑使用单例来确保
应用程序
类只有一个实例。这些参数可以通过
main
传入,但其他代码不需要知道或关心它们的来源


如果你真的想隐藏
main
的参数正在传递给你的
应用程序
构造函数的事实,你可以用一个宏来隐藏它们。

在Linux上,你可以从进程的proc文件系统,即
/proc/$$/cmdline
,获得这些信息:

int pid = getpid();
char fname[PATH_MAX];
char cmdline[ARG_MAX];
snprintf(fname, sizeof fname, "/proc/%d/cmdline", pid);
FILE *fp = fopen(fname);
fgets(cmdline, sizeof cmdline, fp);
// the arguments are in cmdline

对于需要
int-argc,char*argv[]
类型参数的函数,我知道很少有常见的场景。一个明显的例子是GLUT,它的初始化函数从
main()
接收这些参数,这是一种“嵌套的main”场景。这可能是你想要的行为,也可能不是。如果没有,因为没有命名这些参数的约定,只要您的函数有参数解析器,并且您知道自己在做什么,就可以根据需要执行任何操作,硬编码:

int foo = 1;
char * bar[1] = {" "};
或从用户输入读取或以其他方式生成,AFAIK

int myFunc( int foo, char *bar[]){
//argument parser
 {…   …}
return 0;
}

请看这个。

在Windows中,如果需要以
wchar\u t*
的形式获取参数,可以使用
命令行toargvw()


这在使用MinGW时非常方便,因为
gcc
不会将
int\u wmain(int,wchar\u t*)
识别为有效的
main
原型。

传递值并不构成创建依赖关系。您的类不关心那些
argc
argv
值从何而来-它只希望传递它们。但是,您可能希望将这些值复制到某个地方—不能保证它们不会被更改(这同样适用于替代方法,如
GetCommandLine


事实上,恰恰相反——当您使用类似于
GetCommandLine
的东西时,您正在创建一个隐藏的依赖项。突然之间,您不再使用简单的“传递值”语义,而是“神奇地从其他地方获取它们的输入”——再加上前面提到的“值可以随时更改”,这使得您的代码更加脆弱,更不用说无法测试了。解析命令行参数无疑是自动化测试非常有益的情况之一。这是一个全局变量,而不是一个方法参数方法,如果你愿意的话。

听起来你想要的是一个全局变量;您应该做的就是将argc和argv作为参数传递。

我完全同意@gavinb和其他人的观点。您确实应该使用
main
中的参数,并将它们存储或传递到需要它们的地方。这是唯一的便携方式

但是,仅出于教育目的,以下内容适用于我在OS X上使用
clang
、在Linux上使用
gcc

#include <stdio.h>

__attribute__((constructor)) void stuff(int argc, char **argv)
{
    for (int i=0; i<argc; i++) {
        printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
    }
}

int main(int argc, char **argv)
{
    for (int i=0; i<argc; i++) {
        printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
    }
    return 0;
}
原因是
stuff
函数被标记为
\uuuuu属性((构造函数))
,它将在动态链接器加载当前库时运行。这意味着在主程序中,它将在
main
之前运行,并且具有类似的环境。因此,您可以获得参数

但让我重复一遍:这只是出于教育目的,不应该在任何生产代码中使用。它不可移植,可能会在没有警告的情况下在任何时间点损坏。

在C/C++中,如果
main()
没有导出它们,那么就没有直接的方法来访问它们;然而,这并不意味着没有间接的方法。许多类似Posix的系统使用elf格式,该格式通过
int main()
{
    LPWSTR *sz_arglist;
    int n_args;
    int result;
    sz_arglist = CommandLineToArgvW(GetCommandLineW(), &n_args);
    if (sz_arglist == NULL)
    {
        fprintf(stderr, _("CommandLineToArgvW() failed.\n"));
        return 1;
    }
    else
    {
        result = wmain(n_args, sz_arglist);
    }
    LocalFree(sz_arglist);
    return result;
}
#include <stdio.h>

__attribute__((constructor)) void stuff(int argc, char **argv)
{
    for (int i=0; i<argc; i++) {
        printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
    }
}

int main(int argc, char **argv)
{
    for (int i=0; i<argc; i++) {
        printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
    }
    return 0;
}
$ gcc -std=c99 -o test test.c && ./test this will also get you the arguments
stuff: argv[0] = './test'
stuff: argv[1] = 'this'
stuff: argv[2] = 'will'
stuff: argv[3] = 'also'
stuff: argv[4] = 'get'
stuff: argv[5] = 'you'
stuff: argv[6] = 'the'
stuff: argv[7] = 'arguments'
main: argv[0] = './test'
main: argv[1] = 'this'
main: argv[2] = 'will'
main: argv[3] = 'also'
main: argv[4] = 'get'
main: argv[5] = 'you'
main: argv[6] = 'the'
main: argv[7] = 'arguments'