请查看下面的代码
#include <stdio.h>
void printOut()
{
static int i = 0;
if (i < 10)
{
printOut(i);
}
}
int main(int argc, char *argv[])
{
return 0;
}
我猜应该有一个错误,因为我调用了不存在的函数原型。实际上,代码编译好了mingw5编译器,这对我来说很奇怪,然后我改为Borland编译器,我收到一条警告信息说那没有printOut函数的原型,这只是一个警告吗?更重要的是,代码执行良好,没有任何弹出错误窗口。
答案 0 :(得分:6)
在C中,没有任何参数的函数仍然可以获取参数。
这就是它编译的原因。指定它不带任何参数的方法是:
void printOut(void)
这是正确的方法,但不常见,特别是对于那些来自C ++背景的人。
答案 1 :(得分:5)
您的程序行为未定义,因为您定义了printOut()
没有参数,但您使用一个参数调用它。你需要解决它。但是你编写它的方式不需要编译器来诊断问题。 (例如,即使使用-std=c99 -pedantic -Wall -Wextra
-O3,gcc也不会警告参数不匹配。)
原因是历史性的。
预ANSI-C(1989年之前)没有原型;函数声明无法指定预期的参数类型或数量。另一方面,函数定义指定了函数的参数,但不是编译器可以用来诊断不匹配的调用的方式。例如,可以声明具有一个int参数的函数(例如,在头文件中),如下所示:
int plus_one();
并定义(例如,在相应的.c文件中),如下所示:
int plus_one(n)
int n;
{
return n + 1;
}
参数信息隐藏在定义中。
ANSI C添加了原型,所以上面的内容可以写成:
int plus_one(int n);
int plus_one(int n)
{
return n + 1;
}
但是语言继续支持旧式声明和定义,以免破坏现有代码。即使是即将推出的C201X标准仍然允许ANSI之前的功能声明和定义,尽管它们已经淘汰了22年了。
在你的定义中:
void printOut()
{
...
}
您正在使用旧式函数定义。它说printOut没有参数 - 但如果你不正确地调用它,它不会让编译器发出警告。在函数内部,您可以使用一个参数调用它。此调用的行为是 undefined 。它可以悄悄地忽略这个无关紧要的论点 - 或者它可能会破坏堆栈并导致你的程序死得很厉害。 (后者不太可能;由于历史原因,大多数C调用约定都容忍这种错误。)
如果您希望printOut()函数没有参数和,您希望编译器在调用错误时进行投诉,请将其定义为:
void printOut(void)
{
...
}
这是用C语言编写它的唯一正确方法。
当然,如果您只是在程序中进行此更改,然后在printOut()
中添加对main()
的调用,您手上就会有一个无限递归循环。您可能希望printOUt()
采用int
参数:
void printOut(int n)
{
...
}
碰巧,C ++有不同的规则。 C ++源自C,但对后向兼容性的关注较少。当Stroustrup将原型添加到C ++时,他完全放弃了旧式声明。由于无参数函数的特殊情况void
标记,C ++中的void printOut()
明确表示printOut
没有参数,并且调用参数是一个错误。 C ++还允许void printOut(void)
与C兼容,但这可能不经常使用(编写有效C和有效C ++的代码很少有用。)C和C ++是两种不同的语言;您应该遵循您使用的任何语言的规则。