main()
函数如何在不使用省略号(...
)的情况下处理可变数量的参数?对于处理可变数量的参数,函数的最后一个参数应为...
,而main()
函数不是这种情况。
答案 0 :(得分:4)
基本上,main()
是特殊的,它有两种标准定义的形式:
int main(int argc, char **argv)
int main(void)
系统可能支持其他形式;环境也很常见:
int main(int argc, char **argv, char **envp)
这些表格是固定的。唯一不寻常的是系统必须支持前两个系统中的任何一个(并且一些系统也支持其他系统)。
可变数量的命令行参数是通过指向字符串的指针数组(上面的argv
)处理的,与POSIX中的execl()
不同。
另见:
你提到的两个链接非常清楚。这里列出了不同的可能方法,其中没有提到实际使用的方法。
从某种意义上说,没关系;系统只需要工作,制造“系统”的人必须使其工作。您作为使用该系统的程序员不需要知道它是如何工作的;你可以简单地假设它确实有效。
在幕后,通常发生的事情是调用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个参数,通常称为argc
和argv
。 argv
参数是argc
char
数组的数组。命令行参数将传递给argv
中的程序。这个主题有不同的参数确切数量,但主要的签名通常是
int main(int argc, char **argv);
答案 2 :(得分:1)
我将这个问题解释为:main
如何可以采用零参数或两个参数?
虽然细节显然与实现有关,但在大多数实现中,默认的C调用约定是调用者清理堆栈。因此,无论main
的声明是什么,调用argc
的代码都可以完全自由地将两个参数压入堆栈(argv
和main
)。如果声明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)
它接受一个数组和数组长度设置为变量argc
和argv
您可以在此处找到更多数据: