int argc,char * argv []是什么意思?


507

在许多C ++ IDE和编译器中,当它为您生成主要功能时,它看起来像这样:

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

当我不使用IDE而是仅使用命令行编译器来编写C ++时,键入:

int main()

没有任何参数。这是什么意思,对我的程序至关重要吗?


47
如果您的程序将忽略命令行参数,那么您编写的内容就可以了。如果您的程序需要处理命令行参数,则IDE会正确执行。
乔纳森·勒夫勒

30
给黑客的提示:尝试声明int main(int argc, char* argv[], char* envp[])并打印出最后一个参数。;)
ulidtko 2015年

7
@ulidtko教新手在他们的程序中引入漏洞是不好的;)
Gab是好人2016年

13
@Gab简单打印环境变量如何导致漏洞?只是不要将污染的字符串逐字传递给system()调用,数据库查询等。
ulidtko '16

2
@ulidtko有趣的..您能解释一下为什么在使用char **envp参数时不必传递污染的字符串,数据库查询等吗?
詹姆斯大师

Answers:


650

argv以及argc如何main()在C和C ++ 中传递命令行参数。

argc将是指向的字符串数argv。(实际上)这将是1加参数的数目,因为几乎所有实现都将程序名放在该数组的前面。

按照惯例,变量被命名为argcargument count)和argvargument vector),但是可以给它们指定任何有效的标识符:int main(int num_args, char** arg_strings)同等有效。

int main()如果您不打算处理命令行参数,也可以完全省略它们,产生。

请尝试以下程序:

#include <iostream>

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

运行它将./test a1 b2 c3输出

Have 4 arguments:
./test
a1
b2
c3

8
argc可以为0,在这种情况下argv可以为NULL。标准AFAIK允许。我从没听说过可以在实践中做到这一点的系统,但是它肯定可以存在,并且不会违反任何标准。
Chuck 2010年

77
@Chuck:由于“的值argv[argc]应为0”(C ++ 03§3.6.1/ 2),argv因此不能为null。
James McNellis

20
@Chuck:C(至少C99)具有相同的要求。
James McNellis 2010年

2
我想补充一点,尽管有些系统是抽象的,但在大多数系统中都是一样的。例如,在Pascal / Delphi / Lazarus中,您会得到;ParamStr和ParamCount(如果我没记错的话)。我的观点是,当您(如果有)以其他语言/语言编写本机应用程序时,很有可能已定义了上述内容供您使用,并且它们在所有支持的系统中都完全相同(计数/字符串列表)他们。
基督教徒

8
@EmilVikström不,这是一个严重的错误,很可能会导致段错误。*NULL绝对不等于NULL
meagar

52

argc是从命令行传递到程序中的参数数量,并且argv是参数数组。

您可以遍历参数,知道它们的数量,例如:

for(int i = 0; i < argc; i++)
{
    // argv[i] is the argument at index i
}

19

假设您这样运行程序(使用sh语法):

myprog arg1 arg2 'arg 3'

如果您将main声明为int main(int argc, char *argv[]),那么(在大多数环境中),您的main()名字将被称为:

p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));

但是,如果您将main声明为int main(),它将被称为

exit(main());

而且您不会传递参数。

还有两点需要注意:

  1. 这是的仅有的两个标准授权签名main。如果特定平台接受额外的参数或其他返回类型,则这是扩展,不应在可移植程序中依赖它。
  2. *argv[]并且**argv完全等效,因此您可以编写int main(int argc, char *argv[])int main(int argc, char **argv)

2
如果我们是技术人员,则basic.start.main/2明确允许实现的定义版本的main(),如果实现提供两个预定义的版本。因此,它们并非完全不合格。最常见的是envp,它在C和C ++中都广为人知,因此它实际上是C标准的J.5节(通用扩展)中的第一个条目
贾斯汀时间-恢复莫妮卡

1
感谢@Justin的好学问。答案已更新为更正确。
Toby Speight

不知道-我建议您创建一个最小的可复制示例,并进行询问(假设该过程不足以帮助您自己回答它)。
Toby Speight

9

的参数main表示提供到当它被启动该程序的命令行参数。该argc参数表示命令行参数的数量,并且char *argv[]是一个字符串数组(字符指针),这些字符串表示命令行上提供的各个参数。


2
Argv []始终将argv [arg]作为空指针。并且Argv [0]始终是(完整路径)/ executableName作为nul终止的字符串
user3629249 2014年

3
@ user3629249:不一定;argv[0]是启动C程序的程序给它的任何东西argv[0]。就Bash而言,它通常是(也许总是)可执行文件的路径名,但是Bash并不是唯一执行其他程序的程序。允许使用,尽管有些古怪char *args[] = { "cat", "/dev/null", "/etc/passwd", 0 }; execv("/bin/ls", args);。在许多系统argv[0]cat,即使可执行文件是,程序看到的值也将是/bin/ls
乔纳森·莱夫勒

6

main函数可以有两个参数,argcargvargc是一个整数(int)参数,它是传递给程序的参数数量。

程序名称始终是第一个参数,因此程序将至少有一个参数,并且最小值argc为1。但是,如果程序本身具有两个参数,则值argc将为3。

参数argv指向一个字符串数组,称为参数向量。它是函数参数的一维字符串数组。


5
int main();

这是一个简单的声明。它不能接受任何命令行参数。

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

当您的程序必须接受命令行参数时,将使用此声明。当这样运行时:

myprogram arg1 arg2 arg3

argc(或Argument Count)设置为4(四个参数),而argv或(Argument Vectors)将填充指向“ myprogram”,“ arg1”,“ arg2”和“ arg3”的字符串指针。程序调用(myprogram)包含在参数中!

或者,您可以使用:

int main(int argc, char** argv);

这也是有效的。

您可以添加另一个参数:

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

envp参数还包含环境变量。每个条目都遵循以下格式:

VARIABLENAME=VariableValue

像这样:

SHELL=/bin/bash    

环境变量列表以空值结尾。

重要提示:请勿在对!的调用中直接使用argvenvpsystem()。这是一个巨大的安全漏洞,因为恶意用户可以将环境变量设置为命令行命令,并(可能)造成巨大破坏。通常,不要使用system()。通过C库几乎总是存在更好的解决方案。



1

两者的

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

是C或C ++程序入口点的合法定义。Stroustrup:C ++样式和技术常见问题解答详细介绍了一些可能对您的主要功能适用或合法的变体。


4
可能希望在... int main()==> int main(void)...中添加空格以实现兼容性和可读性。我不知道是否所有较旧的C版本都允许void函数在声明中具有空参数列表。
dylnmc

1
@dylnmc不会增加任何可读性,并且在所有C ++版本中都是等效的。仅在C中确实有区别,但仅在声明中而不在定义上。
Ruslan

@Ruslan对不起,我在学习C时就发布了此信息,我可能已经读过,在C的早期版本中,它void是必需的。不要在这方面引用我,我现在知道这是一个愚蠢的评论。不过,它不会受伤。
dylnmc

如果argc <3返回错误怎么办?可能出了什么问题?
AVI
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.