C语言 main() 的非标准签名编译成功



在这段代码中:

int main(int a, int b)
{
    printf(" main(int, int) works nn");
    return 0;
}

main的签名是main(int, int),并且编译成功。为什么?

因为C标准不禁止main的非标准签名(例如参见C99标准的第5.1.2节)。

但是,您会发现,如果您使用 -Wall 标志在 GCC 下编译,1 它会抱怨:

test.c:4: warning: second argument of 'main' should be 'char **'

它假设您想与标准环境交互(即处理命令行参数并返回退出状态),在这种情况下,您必须使用 int main(int, char **)int main(void) 。 如果使用任何其他内容,则参数的内容将未定义。


1.我真的希望 ideone.com 允许您指定编译器标志!

C 标准明确禁止实现提供main的原型(C99, §5.1.2.2.1/1:"程序启动时调用的函数名为 main .该实现没有声明此函数的原型"),并且与原型不匹配(通常)会阻止代码编译。

没有原型,你又回到了过去糟糕的编程,当时由你来确保传递给函数的参数符合它的预期。值得庆幸的是,在main的情况下,签名是如此众所周知,以至于它很少成为问题。

编辑:请注意,如果你想要足够糟糕,实际上甚至可以使用具有两个int参数的版本(尽管该技术在C++中是被禁止的)。 main可以递归调用自己,在这种情况下,可以/可以传递两个int参数:

int main(int a, int b) { 
     if (a == 2)
         main(2, 10);
     printf("%d, %d", a, b);
     return 0;
}

这在目前是相当无用的,但给出了一个大致的想法——你应该在没有命令行参数的情况下运行程序,在这种情况下,a(将接收你通常称之为argc)通常会1(即,它试图传递的唯一参数是 argv[0] 中的程序名称)。在这种情况下,它使用一些其他值调用自己。发生这种情况时,它会打印出这些值。

公平地说,我应该补充一点,这非常接近纯粹的理论,当然不推荐。它可以与大多数典型的实现一起使用,但标准并不能保证这一点。这是一种愚蠢的、迂回的方式来完成它所做的事情——但至少对于大多数典型的编译器来说,无论如何它(只是勉强)是可能的。

没有指定 main 签名的头文件,因此不会报告任何错误。编译器通常只检查返回值,对于 main 的情况(main 签名的警告取决于编译器)。

int main(int a, int b)

这是没有意义的,因为传递给 main 函数的参数总是

int main(int argc,char *argv[])

main 是一个不寻常的功能。它由操作系统调用,并且由于C++可以在许多系统上运行,并且C++标准不能向操作系统编写者指示他们将哪些数据传递给在该操作系统上运行的程序 - 您可以在主函数中编写您喜欢的任何参数,编译器将接受它。

相关内容

  • 没有找到相关文章

最新更新