案例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
不会接受任何参数。那么为什么可以从命令行提供参数呢?
案例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
不会接受任何参数。那么为什么可以从命令行提供参数呢?
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
}
main
函数的函数是由C标准库提供的一个桥接程序,它并不知道也不关心main
函数的声明方式,因此传递给main
的参数将被清除出栈。这种情况不仅局限于main
函数,而是所有C语言函数的普遍调用约定。(使用类似__stdcall
的编译器扩展可以改变调用约定,但如果将其应用于main
或任何由C标准库调用的其他函数,则会导致问题。) - zwolargv
最初是从哪里来的?内核将它与程序一起加载到内存中,作为 execve
操作的一部分,并构造一个初始调用帧,告诉 C 库的启动代码在哪里找到它。它通常位于堆栈的顶部,但不一定是,而且永远不会被释放。 - zwolexit
。请参见https://sourceware.org/git/?p=glibc.git;a=blob;f=csu/libc-start.c的最后部分。 - zwol./a.out something something
并没有直接调用您的主函数,而是由C运行时库调用主函数。命令行参数由加载器/C运行时在堆栈(开头处)的某个区域放置。您可以自行决定是否要访问这些参数。./a.out
),因此您可能也会对这种情况下的错误感到疑惑。gcc program_name.c
编译程序时,编译器将报告可能的编译时警告或错误。由于命令行参数在编译时未传递,因此编译器不知道它,并且程序会忽略该参数。hello
,编译器知道此函数的原型并期望在其调用中不传递任何参数,因此如果传递任何参数,则会报告错误。
argv [0]
)。main
函数与hello
函数不属于同一种类型。 - Jongwaremain(float)
只生成警告,也没有错误。而且只有在使用-Wall选项时才会出现。) - Mr Lister