主要问题是:C编译器如何处理不同源代码中函数main的多个定义? 像:
void main(void)
int main(void)
int main(int argc,char * argv []) ...
我不知道这是否与名称修改有关,只有当C代码与C ++代码链接而不使用extern“C”时才会发生,但我只是通过Linux程序员手册查询(只是简单函数打开(man 2 open),它显示了两个签名:
OPEN(2)Linux程序员手册
NAME
open, creat - open and possibly create a file or device
概要
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
这怎么可行?它的处理方式与主函数的定义类似吗?
答案 0 :(得分:4)
open
实际上没有重载或多个声明。它被声明为open(const char *pathname, int flags, ...)
,第三个参数用va_arg
读取,当mode_t
包含flags
时被解释为O_CREAT
。
如果您有main
的多个定义,或者多个具有相同C名称的符号,则可能会出现链接器错误。
答案 1 :(得分:3)
C编程语言的典型实现可以容忍调用者向函数传递过多参数。在类UNIX系统上,当启动代码调用main
时,它会传递三个参数,就像main
被声明为
int main(int argc, char *argv[], char *environ[]);
其中第三个参数是环境。如果main
定义的参数少于那个,那么一切仍然可以正常工作,就像典型的调用约定一样,额外的参数以不会伤害的方式放置(例如在第一个上面的堆栈上)参数或额外的寄存器)。
从历史上看,open
函数的工作方式类似:open
声明没有原型,因此编译器无法检查传递的参数数量。 open
的定义预期有三个参数,如果你只传递了两个,open
会抓住第三个参数的堆栈中的任何内容,这并不重要,因为第三个参数没有在没有open
的情况下调用O_CREAT
时会影响结果。
答案 2 :(得分:2)
无论如何它确实喜欢。如果您没有以标准禁止的两种方式之一声明main
,或者您以两种方式声明它,编译器可以根据需要将您的汽车传送到月球。任何进一步的合理化都是毫无意义的。
[C99: 5.1.2.2.1/1]:
[..] 应使用int
的返回类型进行定义,且不带参数: [..] < strong>或,带有两个参数 [..]
[C99: 5.1.2.2.1/2]:
如果声明它们,主函数的参数应遵守以下约束: [..]
[C99: 3.4.3/1]:
未定义的行为
行为,使用不可移植或错误的程序结构或错误数据,本国际标准不对此作出任何要求