在许多C++ IDE和编译器中,当它为你生成主函数时,它看起来是这样的:
1
| int main(int argc, char *argv[]) |
当我在没有井手的情况下对C++进行编码时,只需使用命令行编译器,就可以输入:
没有任何参数。这意味着什么,它对我的计划至关重要吗?
- 如果您的程序将忽略命令行参数,那么您所写的就可以了。如果您的程序需要处理命令行参数,那么IDE正在做正确的事情。
- 给黑客一个提示:试着声明int main(int argc, char* argv[], char* envp[])并打印出最后一个参数。;)
- @ulidtko你教新手在他们的程序中引入漏洞是不好的;)
- @环境变量的简单打印如何导致脆弱性?只是不要像往常一样通过用户输入将受污染的字符串逐字传递给system()调用、db查询等。
- @乌利德科很有趣……你能解释一下为什么在使用char **envp参数时不必传递污染的字符串、数据库查询等吗?
- @ulidtko是否在传递命令行参数时调用重载?
EDCOX1 0和EDCOX1 1是如何在C和C++中传递命令行参数到EDCOX1 2。
argc是argv指向的字符串数。实际上,这将是1加上参数个数,因为实际上所有的实现都会在数组前面加上程序名。
变量按约定命名为argc(参数计数)和argv(参数向量),但它们可以被赋予任何有效的标识符:int main(int num_args, char** arg_strings)同样有效。
如果不打算处理命令行参数,也可以完全忽略它们,生成int main()。
尝试以下程序:
1 2 3 4 5 6 7 8
| #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运行将输出
1 2 3 4 5
| Have 4 arguments:
./test
a1
b2
c3 |
- argc可以为0,此时argv可以为空。标准Afaik允许。我从来没有听说过一个在实践中这样做的系统,但是它肯定存在,并且不会违反任何标准。
- 查克:因为"argv[argc]的值应为0"(C++ 03和167;3.6 1/2),EDCOX1·1不能为空。
- @詹姆斯:哦,说得对。我在想c,它对main有着微妙的不同规则。
- @查克:C(至少C99)有同样的要求。
- 我想我应该补充一点,这在大多数系统中都是一样的,尽管它们有时是抽象的。例如,在pascal/delphi/lazarus中,可以得到;paramstr和paramcount(如果内存对我有用的话)。我的观点是,当您(如果有)使用其他语言/OS编写本机应用程序时,很有可能为您定义了上述应用程序,并且它们在所有支持它们的系统中都完全相同(计数/字符串列表)。
- 但是,如果argc为0,argv为空,那么肯定是argv[argc] = *(NULL + 0) = *NULL = NULL = 0,对吗?
- @Emilvikstr&246;m不,这是一个严重的错误,可能会导致SegFault。*NULL绝对不等于NULL。
- @Emilvikstr&246;m你可以做for (char **arg = argv; *arg; arg++) { printf("\t%s
", *arg);},for循环中的arg暗示*arg != NULL,我相信(也就是说,arg是真的)。
- noob问题:在这个上下文中<<做什么?我查了一下,但我能找到的只是"bitshift"的概念,它似乎不是这里发生的事情。
- @地精转而寻找"cout"。它是这个上下文中的流插入操作符。
- 可以。那么,std::cout <<"Have" << argc <<" arguments:" << std::endl;的基本意思是:标准输出发送字符串"have",然后发送整型argc,然后发送字符串"arguments":然后做一些涉及换行符和其他一些我还没有搞清楚的事情?
argc是从命令行传递到程序中的参数数目,argv是参数数组。
您可以循环使用参数,知道它们的数量,比如:
1 2 3 4
| for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
} |
假设您这样运行程序(使用sh语法):
1
| myprog arg1 arg2 'arg 3' |
如果您将您的主机声明为int main(int argc, char *argv[]),那么(在大多数环境中),您的main()将被调用,就像这样:
1 2
| p = {"myprog","arg1","arg2","arg 3", NULL };
exit(main(4, p)); |
但是,如果您将您的主管道声明为int main(),它将被称为
你不能让这些论点通过。
另外需要注意的两件事:
这是main的唯一两个标准授权签名。如果一个特定的平台接受额外的参数或不同的返回类型,那么这是一个扩展,不应该在可移植程序中依赖。
*argv[]和**argv完全相同,所以你可以把int main(int argc, char *argv[])写成int main(int argc, char **argv)。
- 如果我们是技术性的,basic.start.main/2明确允许实现定义的main()的附加版本,前提是实现提供了两个预定义的版本。所以,它们并不完全不符合要求。最常见的是EDCOX1×2,它在C和C++中都是众所周知的,它实际上是C标准的J.5(公共扩展)部分中的第一个条目。
- 谢谢你的漂亮的学究@justin。更新答案以使其更正确。
- 我有一个程序,它也有int main(int argc, char *argv[]),如果argc<3,它会给出一个错误。原因可能是什么?:(我不确定,所以不允许问这个问题,因为它是基于观点的问题:)
- 不知道-我建议您创建一个最小、完整和可验证的示例并询问它(假设这个过程不足以帮助您自己回答)。
main的参数表示程序启动时提供给程序的命令行参数。argc参数表示命令行参数的数目,char *argv[]是一个字符串数组(字符指针),表示命令行上提供的各个参数。
- argv[]始终将argv[arg]作为空指针。argv[0]始终是(完整路径)/可执行名称,作为以nul结尾的字符串
- @用户3629249:不一定;argv[0]是启动c程序的程序赋予它的argv[0]的任何东西。对于bash,它通常(可能总是)是可执行文件的路径名,但bash不是执行其他程序的唯一程序。允许使用:char *args[] = {"cat","/dev/null","/etc/passwd", 0 }; execv("/bin/ls", args);。在许多系统上,程序视为argv[0]的值将是cat,即使可执行文件是/bin/ls。
main函数可以有两个参数,argc和argv。argc是一个整数(int参数),它是传递给程序的参数数目。
程序名始终是第一个参数,因此程序至少有一个参数,argc的最小值为一。但是如果一个程序有两个自变量,那么argc的值将是三个。
参数argv指向一个字符串数组,称为参数向量。它是一个一维的函数参数字符串数组。
- 它也很有用:crasseux.com/books/ctutorial/argc-and-argv.html
这是一个简单的声明。它不能接受任何命令行参数。
1
| int main(int argc, char* argv[]); |
当程序必须采用命令行参数时,使用此声明。像这样跑的时候:
1
| myprogram arg1 arg2 arg3 |
argc或参数计数将被设置为4(四个参数),并且argv或参数向量将被填充为指向"myprogram"、"arg1"、"arg2"和"arg3"的字符串指针。程序调用(myprogram包含在参数中!
或者,您可以使用:
1
| int main(int argc, char** argv); |
这也是有效的。
您可以添加另一个参数:
1
| int main (int argc, char *argv[], char *envp[]) |
envp参数还包含环境变量。每个条目都遵循以下格式:
1
| VARIABLENAME=VariableValue |
这样地:
环境变量列表以空结尾。
重要提示:不要在调用system()时直接使用任何argv或envp值!这是一个巨大的安全漏洞,因为恶意用户可以将环境变量设置为命令行命令,并(可能)造成巨大的破坏。一般来说,不要使用system()。几乎总是有一个更好的解决方案通过C库实现。
第一个参数是提供的参数个数,第二个参数是表示这些参数的字符串列表。
- argv[0]中的第一个条目是程序名,而不是参数
- @带有程序路径的用户3629249程序名。;)
两个
1 2
| int main(int argc, char *argv[]);
int main(); |
是C或C++程序入口点的法律定义。Stroustrup:C++风格和技术FAQ详细描述了一些可能的或合法的对你的主要功能的变化。
- 可能想让空虚…int main()==>int main(void)…为了兼容性和可读性。我不知道C的所有旧版本是否都允许void函数在声明中有一个空参数列表。
- DelnMC没有给出任何可读性增益,并且在所有C++版本中都是等价的。只有在C中,这才有区别,但只在声明中,而不是在定义中。
- @Ruslan对不起,我刚学C的时候就把这个贴出来了,我可能读过,在C的早期版本中,需要void。不要引用我的话,我现在知道这是一个有点愚蠢的评论。不过,它不会受伤。
- 如果argc<3返回错误怎么办?有什么可能出错?