8
6.7.6.3 Function declarators (including prototypes)

标准的这一部分处理'Identifier list''Parameter type list'

首先,函数声明(不是定义)与函数原型相同。我对么?如果这是正确的,那么为什么标准说'including prototypes'

我无法理解函数声明之间'Identifier list''Parameter type list'相对于函数声明的区别。

int fun();    // Declaration
int fun(int x)// Definition, but the signature doesn't match and it works.
{ return x; }

谁能解释一下,我很困惑?

4

3 回答 3

14

函数声明与函数原型不同。原型是一种特殊的声明。例如,这是一个不是原型的函数声明

int foo();

以下声明是原型

int foo(int a, double b);
int bar(char, float);
float baz(void);

即原型是描述函数参数的数量和类型的声明。非原型声明没有说明参数。

现在,除了“现代”函数定义之外,C 语言仍然支持旧的 K&R 风格的函数定义。K&R 风格的函数定义如下

int foo(a, b)
int a;
double b;
{
  ...
}

“现代”函数定义如下所示

int foo(int a, double b)
{
  ...
}

如您所见,K&R 样式的参数列表只是a, b. 它包括参数名称,但不包括它们的类型。这就是语法所指的标识符列表。“现代”参数列表是int a, double b,这就是语法所指的参数类型列表

标识符列表是 K&R 风格的函数定义语法的一部分,而参数类型列表是“现代”函数定义语法的一部分。

另请注意,在 C 语言中,声明

int foo();

并不意味着foo不需要任何参数。这意味着foo采用未指定数量的参数,即它只是在调用点关闭参数类型检查、参数编号检查和参数转换foo。这样的“签名”将foo与任何参数列表的定义相匹配。这个

int foo(int x)
{
  ...
}

foo是如上所示声明的完全有效的定义。声明它的事实()只是意味着编译器不会在调用时验证参数。你有责任确保你调用的参数类型foo只有一个。int

于 2013-09-16T05:20:16.280 回答
2

在 C11 标准中

6.7.6.3 函数声明符(包括原型)
约束

D( parameter-type-list )
or
D( identifier-listopt )  

在声明函数时,您不需要提供标识符列表。但是你至少应该提到类型列表

例子:

int sum(int,int); //declaration  

int sum(int a,int b); //declaration

两者都是相同功能的声明。

但是第二个您还提到了可选的标识符。

于 2013-09-16T05:22:13.300 回答
1

C11(ISO/IEC 9899:201x) §6.2.1标识符范围第 2 节

函数原型是声明其参数类型的函数的声明。

以您的示例为例,对于函数定义

int fun(int x)
{ return x; }

int func(int x);和都是int func();有效的函数声明。但只有前者是函数原型。

您甚至可以在函数声明中省略变量名,例如int func(int);. 尽管由于缺乏可读性,我们通常不喜欢这样做。

于 2013-09-16T05:26:54.570 回答