案例1:
void hello(void) {
//something
}
int main()
{
hello(1); //error
return 0;
}
案例2:
int main(void) {
//something
return 0;
}
执行:
./a.out something something //No error, Why?
为什么没有错误? main
将无法接受任何争论。那么为什么可以从命令行提供参数呢?
答案 0 :(得分:14)
因为C编译器和命令行解释器(或用于调用程序的任何东西)是不同的东西。
C语言允许以各种方式声明main()。
命令行解释器将使程序可以使用任何参数。如果程序忽略它们,那就不是它的业务。
命令行解释器甚至不知道您使用C编译程序。在我的计算机上,程序可以用C,C ++,Objective-C,Objective-C ++,Swift,Fortran,Ada等编写。这些编译器中的每一个都可能会或可能不会从命令行接受命令。
答案 1 :(得分:9)
不检查规范或编译结果,它不会导致错误,因为C运行时将获取参数并将它们传递给main()
,但是这种类型的main()
将忽略传递的参数,并且如果调用者有责任清理用作参数的内存(堆栈),那么就不会产生任何问题,就像获取一些参数而不在代码中使用它们一样。
此代码不会在C:
中发出错误void hello(); // in C, the compiler won't check arguments
int main() {
hello(1); //no error
return 0;
}
void hello(void) {
//something
}
答案 2 :(得分:5)
因为./a.out something something
没有直接调用您的主函数。主要功能由c运行时库调用。命令行参数由loader / c运行时放置在堆栈中的某个区域(最开始)。如果您想要访问这些参数,则由您决定。
正如其中一条评论所指出的那样,至少有一个命令行参数始终是传递的(程序的名称./a.out
是准确的) - 所以你一定想知道一个错误案件也是如此。
答案 3 :(得分:3)
回想一下,ISO C指定main
:int main(void)
和int main(int, char *[])
及其等效版本的两个可能签名,如int main(int, char **)
因为数组到指针的衰减。详细介绍here。
可以通过考虑相反的问题来回答这个问题: C运行时如何知道要调用的main
? C没有重载决议!这是here的解释。简而言之,其他人被推,但没有被访问,因为C没有迹象表明这样做。
答案 4 :(得分:2)
使用gcc program_name.c
编译程序时,编译器将报告任何可能的编译时警告或错误。由于命令行参数在编译时没有传递,编译器不知道它,程序只是忽略那些参数。
在hello
的情况下,编译器知道该函数的原型,并且期望在其调用中不传递参数,因此在传递任何参数的情况下报告错误。