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

C main()的非标准签名已成功编译,c,main,C,Main,在此代码中: int main(int a, int b) { printf(" main(int, int) works \n\n"); return 0; } main的签名是main(int,int),和。为什么?因为C标准不禁止非标准签名用于main(例如,参见C99标准第5.1.2节) 但是,您会发现,如果您在GCC下使用-Wall标志进行编译,1它会抱怨: test.c:4: warning: second argument of 'main' should be

在此代码中:

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

main
的签名是
main(int,int)
,和。为什么?

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

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

test.c:4: warning: second argument of 'main' should be 'char **'
它假设您希望与标准环境交互(即处理命令行参数并返回退出状态),在这种情况下,您必须使用
intmain(int,char**)
intmain(void)
。如果您使用其他任何东西,参数的内容将是未定义的



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

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

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

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

main是一个不寻常的函数,由操作系统调用,由于C++可以在许多系统上运行,C++标准不能规定OS作者将什么数据传递给在该OS上运行的程序——可以编写任何在主要函数中喜欢的参数,编译器会接受它。

< P>特别禁止C实现为<代码>主< /代码>提供原型。(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签名的头文件,因此不会报告任何错误。
我认为您不在这里。@nims编译器报告的错误不是头文件标识的错误,因为main没有头文件。该错误是由特定于main的编译器的特殊逻辑生成的。关于n注(1):选择“C99严格”看起来像通过-std=C99-pedantic-Werror
int main(int a, int b) { 
     if (a == 2)
         main(2, 10);

     printf("%d, %d", a, b);
     return 0;
}