在C语言中用一个参数定义函数时,为什么不能调用不带参数的函数?

时间:2018-11-03 17:42:00

标签: c

我知道我不应该定义任何类似的功能。但是我喜欢尝试极限,所以我写了一些这样的代码:

#include <stdio.h>

void func(a)
{
    printf("%d\n", a);
}

int main()
{
    func();
    func();
    func();
    return 0;
}

我真的不是在寻找任何输出,但是我看到的输出很奇怪。

输出为

1
0
0

为什么?那些1或0是哪里来的?

(我正在使用CygWin和Eclipse dut btw。)

3 个答案:

答案 0 :(得分:2)

您的程序无效。

gcc 8.2抱怨:

$ gcc -Wall -Wextra -pedantic -std=c17 t.c
test.c: In function ‘func’:
test.c:3:6: warning: type of ‘a’ defaults to ‘int’ [-Wimplicit-int]
 void func(a)

自C99以来,所有函数均要求其参数具有有效的类型(以前是"implicit int"规则-如果未指定,则函数参数/返回类型假定为int)。但是您的程序在C89中也无效,因为您实际上没有传递任何参数。所以您看到的是undefined behaviour的结果。

答案 1 :(得分:2)

当您不为变量定义类型时,int被编译器视为默认类型。

warning: type of 'a' defaults to 'int' [-Wimplicit-int]
 void func(a)

因此,它正在打印int a包含的不确定值。

答案 2 :(得分:0)

在1989年ANSI C标准之前,用C定义函数的唯一方法是不指定任何参数的数量和类型。 (该语言的旧版本称为“ K&R C”,因为在Kernighan和Ritchie的第一版“ C编程语言”中已有介绍。)您正在使用旧式的函数定义:

void func(a)
{
    printf("%d\n", a);
}

此处a是参数的名称。它隐式为int类型,但该信息未用于确定对func的调用的正确性。

C89添加了 prototypes ,可让您以一种在编译器看到对该函数的调用时检查的方式指定参数的类型:

void func(int a)
{
    printf("%d\n", a);
}

因此,在1989年C语言版本中,您的程序是合法的(从某种意义上说,不需要在编译时诊断任何错误),但是其行为是不确定的。 func可能会抓住它期望调用者放置自变量值的位置中的任何值。由于未传递任何参数,因此该值将是垃圾。但是该程序原则上可以执行任何操作。

该语言的1999年版本删除了“隐式int”规则,因此即使使用旧式定义,也不再假设a的类型为int

但是,即使最新的2011版本的C都没有删除旧式的函数定义和声明。但自1989年以来,它们就正式过时了。

底线:始终使用原型。旧式的函数定义和声明仍然是合法的,但是从来没有(或很少有)使用它们的任何正当理由。不幸的是,如果您不小心使用了编译器,则不一定会警告您。

(您还为main使用了旧式定义。int main()最好写为int main(void)。这比其他函数的问题少,因为{{ 1}}通常不被称为,但这仍然是一个好习惯。)