我刚刚遇到了一些人的C代码,我很困惑为什么它要编译。有两点我不明白。

与实际函数定义相比,函数原型没有参数。 函数定义中的形参没有类型。


#include <stdio.h>

int func();

int func(param)
{
    return param;
}

int main()
{
    int bla = func(10);    
    printf("%d", bla);
}

为什么会这样? 我已经在几个编译器中测试了它,它工作得很好。


当前回答

如果函数返回类型和形参列表上没有给出类型,则C语言假定为int。只有遵循这条规则,才有可能发生奇怪的事情。

函数定义是这样的。

int func(int param) { /* body */}

如果它是一个原型,你写

int func(int param);

在原型中,你只能指定参数的类型。参数名称为非必选项。所以

int func(int);

同样,如果你没有指定参数类型,但名称int被假设为类型。

int func(param);

如果你走得更远,跟着也行。

func();

当你编写func()时,编译器假设int func()。但是不要把func()放在函数体中。这是一个函数调用

其他回答

正如@Krishnabhadra所说,其他用户之前的所有回答都有正确的解释,我只是想对一些观点做更详细的分析。

在Old-C中,就像在ANSI-C中一样,“无类型的形式参数”,取你的工作寄存器的尺寸或指令深度能力(阴影寄存器或指令累积周期),在一个8位MPU中,将是一个int16,在一个16位MPU中,将是一个int16,等等,在这种情况下,64位架构可以选择编译选项,如:-m32。

虽然它在高层的实现看起来更简单, 对于传递多个参数,程序员在控制维度数据类型步骤中的工作,变得更加苛刻。

在其他情况下,对于一些微处理器架构,ANSI编译器自定义,利用一些旧的特性来优化代码的使用,迫使这些“无类型的形式参数”的位置在工作寄存器内部或外部工作,今天你几乎可以使用“volatile”和“register”。

但值得注意的是,最现代的编译器, 不区分这两种类型的参数声明。

在linux下使用gcc编译的例子:

  在任何情况下,原型的语句在本地是没有用的,因为没有参数的调用对这个原型的引用将是疏忽。 如果您使用带有“无类型形式参数”的系统进行外部调用,则继续生成声明性原型数据类型。

是这样的:

int myfunc(int param);

空参数列表表示“任何参数”,因此定义没有错。 缺失的类型被假定为int型。

我认为任何通过这一点的构建都缺乏配置的警告/错误级别,尽管如此,允许实际代码没有任何意义。

在C语言中,func()意味着你可以传递任意数量的参数。如果你不想要参数,那么你必须声明为func(void)。传递给函数的类型,如果没有指定,默认为int。

如果函数返回类型和形参列表上没有给出类型,则C语言假定为int。只有遵循这条规则,才有可能发生奇怪的事情。

函数定义是这样的。

int func(int param) { /* body */}

如果它是一个原型,你写

int func(int param);

在原型中,你只能指定参数的类型。参数名称为非必选项。所以

int func(int);

同样,如果你没有指定参数类型,但名称int被假设为类型。

int func(param);

如果你走得更远,跟着也行。

func();

当你编写func()时,编译器假设int func()。但是不要把func()放在函数体中。这是一个函数调用

int func ();是一个过时的函数声明,从没有C标准的日子,即K&R C的日子(1989年之前,第一个“ANSI C”标准发布)。

记住,在《K&R C》中还没有原型,关键字void也还没有被发明出来。你所能做的就是告诉编译器函数的返回类型。K&R C中的空参数列表表示“未指定但固定”的参数数量。Fixed意味着每次调用函数时必须使用相同数量的参数(而不是像printf这样的可变参数函数,每次调用时参数的数量和类型都可以变化)。

许多编译器会诊断这个构造;特别是gcc - wstrict - prototyping会告诉你“函数声明不是原型”,这是正确的,因为它看起来像一个原型(特别是如果你被c++毒害了!),但不是。这是一个老式的K&R C返回类型声明。

经验法则:永远不要让空参数列表声明为空,具体使用int func(void)。 这将K&R返回类型声明转换为适当的C89原型。编译器很高兴,开发人员很高兴,静态检查器也很高兴。不过,那些被c++的^W^Wfond误导的人可能会畏缩,因为当他们尝试练习外语技能时,他们需要输入额外的字符:-)