为什么在将 main 声明为 `int main(void)` 时传递命令行参数时没有错误?
Why there is no error when passing command line arguments when declaring main as `int main(void)`?
案例一:
void hello(void) {
//something
}
int main()
{
hello(1); //error
return 0;
}
案例二:
int main(void) {
//something
return 0;
}
执行:
./a.out something something //No error, Why?
为什么没有报错? main
将无法接受任何参数。那么为什么可以从命令行提供参数呢?
不检查规范和编译结果,不会导致错误,因为 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
}
因为./a.out something something
不是直接调用你的main函数。 C 运行时库正在调用 main 函数。 loader/c 运行时将命令行参数放置在堆栈某处(最开始)的区域中。是否要访问这些参数取决于您。
此外,正如其中一条评论中所指出的那样,至少始终会传递一个命令行参数(准确地说是程序名称 ./a.out
)——所以您一定想知道一个错误在那种情况下也是如此。
因为 C 编译器和命令行解释器(或用于调用程序的任何东西)是不同的东西。
C 语言允许以多种方式声明 main ()。
命令行解释器将使程序可以使用任何参数。如果程序忽略它们,那就是 none 的事情了。
命令行解释器甚至不知道您使用C 来编译您的程序。在我的电脑上,程序可以用 C、C++、Objective-C、Objective-C++、Swift、Fortran、Ada 等语言编写。这些编译器中的每一个都可能会或可能不会做一些事情来接受来自命令行的命令。
当您使用 gcc program_name.c
编译程序时,编译器将报告任何可能的编译时警告或错误。由于命令行参数没有在编译时传递,编译器不知道它,程序只是忽略这些参数。
在 hello
的情况下,编译器知道此函数的原型,并且不希望在其调用中传递任何参数,因此在向其传递任何参数的情况下报告错误。
回想一下,ISO C 指定了 main
的两个可能签名:int main(void)
和 int main(int, char *[])
及其等效版本,例如 int main(int, char **)
,因为数组到-指针衰减。对此有更详细的介绍 here。
这个问题可以通过考虑相反的问题来回答:C 运行时如何知道 main
调用什么? C 没有重载决议!这是解释here。简而言之,其他人被推送但未被访问,因为 C 没有指示这样做。
案例一:
void hello(void) {
//something
}
int main()
{
hello(1); //error
return 0;
}
案例二:
int main(void) {
//something
return 0;
}
执行:
./a.out something something //No error, Why?
为什么没有报错? main
将无法接受任何参数。那么为什么可以从命令行提供参数呢?
不检查规范和编译结果,不会导致错误,因为 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
}
因为./a.out something something
不是直接调用你的main函数。 C 运行时库正在调用 main 函数。 loader/c 运行时将命令行参数放置在堆栈某处(最开始)的区域中。是否要访问这些参数取决于您。
此外,正如其中一条评论中所指出的那样,至少始终会传递一个命令行参数(准确地说是程序名称 ./a.out
)——所以您一定想知道一个错误在那种情况下也是如此。
因为 C 编译器和命令行解释器(或用于调用程序的任何东西)是不同的东西。
C 语言允许以多种方式声明 main ()。
命令行解释器将使程序可以使用任何参数。如果程序忽略它们,那就是 none 的事情了。
命令行解释器甚至不知道您使用C 来编译您的程序。在我的电脑上,程序可以用 C、C++、Objective-C、Objective-C++、Swift、Fortran、Ada 等语言编写。这些编译器中的每一个都可能会或可能不会做一些事情来接受来自命令行的命令。
当您使用 gcc program_name.c
编译程序时,编译器将报告任何可能的编译时警告或错误。由于命令行参数没有在编译时传递,编译器不知道它,程序只是忽略这些参数。
在 hello
的情况下,编译器知道此函数的原型,并且不希望在其调用中传递任何参数,因此在向其传递任何参数的情况下报告错误。
回想一下,ISO C 指定了 main
的两个可能签名:int main(void)
和 int main(int, char *[])
及其等效版本,例如 int main(int, char **)
,因为数组到-指针衰减。对此有更详细的介绍 here。
这个问题可以通过考虑相反的问题来回答:C 运行时如何知道 main
调用什么? C 没有重载决议!这是解释here。简而言之,其他人被推送但未被访问,因为 C 没有指示这样做。