在许多 C++ IDE 和编译器中,当它为您生成 main 函数时,它看起来像这样:
int main(int argc, char *argv[])
当我在没有 IDE 的情况下仅使用命令行编译器编写 C++ 代码时,我键入:
int main()
没有任何参数。这是什么意思,对我的计划至关重要吗?
int main(int argc, char* argv[], char* envp[])
并打印出最后一个参数。 ;)
system()
调用、数据库查询等。像往常一样使用用户输入。
char **envp
参数时不必传递受污染的字符串、数据库查询等?
argv
和 argc
是命令行参数在 C 和 C++ 中传递给 main()
的方式。
argc
将是 argv
指向的字符串数。这将(实际上)是 1 加上参数的数量,因为几乎所有的实现都会将程序的名称添加到数组中。
按照约定,变量被命名为 argc
(argument count)和 argv
(argument 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
argc
是从命令行传入程序的参数数量,argv
是参数数组。
您可以遍历参数,知道它们的数量,例如:
for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
}
假设您这样运行程序(使用 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());
你没有得到通过的论点。
还有两点需要注意:
这是 main 仅有的两个标准强制签名。如果特定平台接受额外的参数或不同的返回类型,那么这是一个扩展,不应该在可移植程序中依赖。 *argv[] 和 **argv 是完全等价的,所以你可以把 int main(int argc, char *argv[]) 写成 int main(int argc, char **argv)。
basic.start.main/2
明确允许实现定义的 main()
附加版本,前提是实现提供两个预定义版本。因此,它们并非完全不合格。最常见的是 envp
,它在 C 和 C++ 中都非常有名,以至于 it's literally the very first entry in section J.5 (Common extensions) of the C standard。
argv
的最后一个元素是否总是 NULL
?我正在阅读一些代码,其中调用了 argv[1]
而没有检查 argc > 1
,而编写代码的人显然希望具有正确的值或 NULL
。
argv[argc]
shall be 0
.
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
环境变量列表以空值结尾。
重要提示:请勿在对 system()
的调用中直接使用任何 argv
或 envp
值!这是一个巨大的安全漏洞,因为恶意用户可以将环境变量设置为命令行命令并(可能)造成巨大的破坏。一般来说,不要使用 system()
。几乎总是有通过 C 库实现的更好的解决方案。
main
的参数表示程序启动时提供给程序的命令行参数。 argc
参数表示命令行参数的数量,char *argv[]
是一个字符串数组(字符指针),表示命令行上提供的各个参数。
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
指向一个字符串数组,称为参数向量。它是函数参数的一维字符串数组。
第一个参数是提供的参数数量,第二个参数是表示这些参数的字符串列表。
让我们考虑一下声明:
int main (int argc, char *argv[])
在上面的声明中,名为 argv
的第二个参数的类型实际上是一个 char**
。也就是说,argv
是一个 指针,指向一个指向 char
的指针。这是因为由于类型衰减,char* []
衰减 为 char**
。例如,下面给出的声明是等价的:
int main (int argc, char *argv[]); //first declaration
int main (int argc, char **argv); //RE-DECLARATION. Equivalent to the above declaration
换句话说,argv
是一个指针,它指向具有 char*
类型元素的数组的第一个元素。此外,数组的每个元素 argv[i]
(具有 char*
类型的元素)本身都指向一个字符,该字符是 null 终止字符串的开始。也就是说,每个元素 argv[i]
都指向数组的第一个元素,其元素类型为 char
(而不是 const char
)。为说明目的给出了一个图表:
https://i.stack.imgur.com/4TpCz.png
正如在其他答案中已经说过的,当我们想要使用命令行参数时,会使用这种形式的 main
声明。
两者的
int main(int argc, char *argv[]);
int main();
是 C 或 C++ 程序入口点的合法定义。 Stroustrup: C++ Style and Technique FAQ 详细说明了您的主要功能可能或合法的一些变体。
int main()
==> int main(void)
...为了兼容性和可读性。我不知道是否所有旧版本的 C 都允许 void 函数在声明中具有空参数列表。
void
。不要引用我的话,我现在知道这是一个有点愚蠢的评论。不过,它不会受伤。
argv[argc] = *(NULL + 0) = *NULL = NULL = 0
,对吧?*NULL
绝对不等于NULL
。for (char **arg = argv; *arg; arg++) { printf("\t%s\n", *arg);}
我相信 for 循环中的 *arg 暗示*arg != NULL
(即当 *arg 为真时)。./test a1 b2 c3
。