请看下面我的代码
#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 函数原型,这只是一个警告吗?更重要的是,代码执行良好,没有弹出任何错误窗口。
在 C 中,没有任何参数的函数仍然可以带参数。
这就是它编译的原因。指定它不带任何参数的方法是:
void printOut(void)
这是正确的方法,但不太常见,尤其是对于那些具有 C++ 背景的人来说。
你的程序的行为是未定义的,因为你定义
printOut()
时没有参数,但你用一个参数调用它。 你需要修复它。 但是您已经以编译器不需要诊断问题的方式编写了它。 (例如,gcc 不会警告参数不匹配,即使使用 -std=c99 -pedantic -Wall -Wextra
-O3。)
这是有历史原因的。
ANSI C 之前(1989 年之前)没有原型;函数声明无法指定预期的参数类型或数量。 另一方面,函数definition指定了函数的参数,但不是以编译器可以用来诊断不匹配调用的方式。 例如,一个带有一个 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 没有参数——但如果您错误地调用它,它不会让编译器警告您。 在你的函数内部,你可以用一个参数来调用它。 此调用的行为是未定义。 它可能会悄悄地忽略无关的参数——或者它可能会破坏堆栈并导致你的程序可怕地死掉。 (后者不太可能;由于历史原因,大多数 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++ 是两种不同的语言;无论您使用哪种语言,您都应该遵守其规则。