main()如何处理不带省略号的可变数量的参数?

时间:2014-12-21 07:55:04

标签: c++ c

main()函数如何在不使用省略号(...)的情况下处理可变数量的参数?对于处理可变数量的参数,函数的最后一个参数应为...,而main()函数不是这种情况。

4 个答案:

答案 0 :(得分:4)

基本上,main()是特殊的,它有两种标准定义的形式:

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

系统可能支持其他形式;环境也很常见:

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

这些表格是固定的。唯一不寻常的是系统必须支持前两个系统中的任何一个(并且一些系统也支持其他系统)。

可变数量的命令行参数是通过指向字符串的指针数组(上面的argv)处理的,与POSIX中的execl()不同。

另见:


rahul manglani commented

  

你提到的两个链接非常清楚。这里列出了不同的可能方法,其中没有提到实际使用的方法。

从某种意义上说,没关系;系统只需要工作,制造“系统”的人必须使其工作。您作为使用该系统的程序员不需要知道它是如何工作的;你可以简单地假设它确实有效。

在幕后,通常发生的事情是调用main()的'start'函数做了一些修复工作(特别是在C ++程序的情况下,很多修复工作 - 比如确保所有的必须在main()启动之前执行的构造函数实际上已执行),但以固定序列结束,例如:

exit(main(argc, argv, environ));

environ是一个全局变量extern char **environ;,现在在<unistd.h>中声明并包含指向环境变量的指针。'start'代码必须确保设置为;因此,将environ作为参数传递给main()是微不足道的。)

这会使用固定参数列表调用main(),并在返回时调用exit()。实际上,我相信Apple更进一步,并将第四个论点传递给main()。如果被调用函数被定义为int main(void) { … },它只是忽略它传递的参数;如果它被定义为int main(int argc, char **argv) { … },它可以像往常一样访问命令行参数;如果它被定义为int main(int argc, char **argv, char **envp) { … },那么它也可以访问环境。

通常,系统设置为使额外的参数不会造成损害。这就是为什么C在其调用约定中不常见的原因,这就是为什么被调用的函数不会清理压入堆栈的参数 - 被调用的函数不知道有多少参数实际被压入堆栈。它假设提供了它所期望的那些并且没有问题地使用它们,但是调用代码知道它推送了什么以便它可以正确地清理。如果被调用的函数需要N个参数但是调用者传递M个参数并且M <0,则会出现最大的问题。 N.(还有推出类型的问题和这些类型的大小等,但这是一个二阶问题。)

答案 1 :(得分:2)

在C / C ++中,main需要2个参数,通常称为argcargvargv参数是argc char数组的数组。命令行参数将传递给argv中的程序。这个主题有不同的参数确切数量,但主要的签名通常是

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

答案 2 :(得分:1)

我将这个问题解释为:main如何可以采用零参数或两个参数?

虽然细节显然与实现有关,但在大多数实现中,默认的C调用约定是调用者清理堆栈。因此,无论main的声明是什么,调用argc的代码都可以完全自由地将两个参数压入堆栈(argvmain)。如果声明main没有参数,那么main只是无法访问它收到的参数的值。在main返回后,调用代码清除堆栈。

应该指出的是,main在这个意义上并不特别。试试这个:

int printf();
int main() { printf("Hello, world!\n"); }

C编译器很乐意允许您调用printf,即使缺少#include <stdio.h>指令,它也不知道printf实际需要多少个参数。据推测,调用main的代码在概念上是这样的:

int main(int argc, char** argv); /* declare "main" */
main(argc, argv);                /* call "main" */

如果main的定义实际上指定了零参数,这仍然有效(尽管我认为如果实际这样做,它在技术上将是未定义的行为)。

对于C ++,尽管main的链接未被标准指定,但大多数实现只是将其视为具有C链接,因此名称不会被破坏,并且上面的所有内容仍然适用。 / p>

答案 3 :(得分:0)

它接受一个数组和数组长度设置为变量argcargv

来处理它

您可以在此处找到更多数据:

http://crasseux.com/books/ctutorial/argc-and-argv.html