C编译器如何处理不同的主函数定义?

时间:2016-06-14 18:23:03

标签: c linux name-mangling

主要问题是: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);

这怎么可行?它的处理方式与主函数的定义类似吗?

3 个答案:

答案 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]: 未定义的行为
  行为,使用不可移植或错误的程序结构或错误数据,本国际标准不对此作出任何要求