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

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


#include <stdio.h>

int func();

int func(param)
{
    return param;
}

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

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


当前回答

其他答案都是正确的,但只是为了完成

A function is declared in the following manner: return-type function-name(parameter-list,...) { body... } return-type is the variable type that the function returns. This can not be an array type or a function type. If not given, then int is assumed. function-name is the name of the function. parameter-list is the list of parameters that the function takes separated by commas. If no parameters are given, then the function does not take any and should be defined with an empty set of parenthesis or with the keyword void. If no variable type is in front of a variable in the paramater list, then int is assumed. Arrays and functions are not passed to functions, but are automatically converted to pointers. If the list is terminated with an ellipsis (,...), then there is no set number of parameters. Note: the header stdarg.h can be used to access arguments when using an ellipsis.

为了完整起见。来自C11规范6:11:6(第179页)

使用带有空括号的函数声明器(不是 原型格式参数类型声明器)是过时的 特性。

其他回答

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

如果函数声明没有形参,即为空,则它将接受不指定数量的参数。如果你想让它不带参数,那么将其更改为:

int func(void);

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

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

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

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

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

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

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

是这样的:

int myfunc(int param);

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

函数定义是这样的。

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

如果它是一个原型,你写

int func(int param);

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

int func(int);

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

int func(param);

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

func();

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

在旧式的声明器中,

标识符列表必须不存在 声明器用于函数定义的头部 (Par.A.10.1)。参数类型信息不为 由声明提供。例如,声明

int f(), *fpi(), (*pfi)();

声明一个函数f返回一个整数,一个函数fpi返回一个整数指针,>和一个指针pfi返回一个整数函数。其中没有指定>的参数类型;它们是老式的。

在new-style声明中

Int strcpy(char *dest, const char *source), rand(void);

Strcpy是 函数返回int,有两个参数,第一个是字符 指针,第二个指针指向常量字符

来源:- K&R书

我希望这消除了你的疑虑。