函数定义
函数定义将函数体(一系列声明和语句)与函数名和参数列表关联起来。与函数声明不同,函数定义只允许在文件作用域内(没有嵌套函数)。
C 支持两种不同形式的函数定义
attr-spec-seq(可选) specifiers-and-qualifiers parameter-list-declarator function-body | (1) | ||||||||
specifiers-and-qualifiers identifier-list-declarator declaration-list function-body | (2) | (直至 C23) | |||||||
其中
属性说明序列 | - | (C23)应用于函数的属性的可选列表 |
specifiers-and-qualifiers | - | 以下各项的组合 |
parameter-list-declarator | - | 用于函数类型的声明符,它使用参数列表来指定函数参数 |
identifier-list-declarator | - | 用于函数类型的声明符,它使用标识符列表来指定函数参数 |
declaration-list | - | 声明序列,声明identifier-list-declarator中的每个标识符。这些声明不能使用初始化器,并且唯一允许的存储类说明符是register。 |
function-body | - | 一个复合语句,即一个用大括号括起来的声明和语句序列,每当调用此函数时都会执行 |
int max(int a, int b) { return a>b?a:b; } double g(void) { return 0.1; }
int max(a, b) int a, b; { return a>b?a:b; } double g() { return 0.1; }
目录 |
[编辑] 解释
与函数声明一样,函数的返回类型(由specifiers-and-qualifiers中的类型说明符决定,并可能像声明中通常那样被declarator修改)必须是完整的非数组对象类型或void类型。如果返回类型是 cvr-qualified,则为了构造函数类型,它会调整为非限定版本。
与函数声明一样,为了构造函数类型,参数的类型会从函数调整为指针,从数组调整为指针,并且为了确定兼容函数类型,所有参数类型的顶层 cvr-限定符都被忽略。
与函数声明不同,不允许使用未命名的形式参数(否则,旧式 (K&R) 函数定义中会出现冲突),即使它们在函数中未使用,也必须命名。唯一的例外是特殊参数列表(void)。 |
(直至 C23) |
形式参数在函数定义中可以不命名,因为旧式(K&R)函数定义已被移除。未命名的参数在函数体内无法通过名称访问。 |
(自 C23 起) |
int f(int, int); // declaration // int f(int, int) { return 7; } // Error until C23, OK since C23 int f(int a, int b) { return 7; } // definition int g(void) { return 8; } // OK: void doesn't declare a parameter
在函数体内,每个命名参数都是一个左值表达式,它们具有自动存储期和块作用域。参数在内存中的布局(或者它们是否存储在内存中)未指定:它是调用约定的一部分。
int main(int ac, char **av) { ac = 2; // parameters are lvalues av = (char *[]){"abc", "def", NULL}; f(ac, av); }
有关函数调用机制的其他详细信息,请参见函数调用运算符,有关从函数返回的信息,请参见return。
__func__在每个函数体内,特殊预定义变量__func__,具有块作用域和静态存储期,可用,如同紧接在开大括号后由以下内容定义: static const char __func__[] = "function name"; |
(C99 起) |
[编辑] 注意
参数列表必须明确地出现在声明符中,不能从 typedef 继承
typedef int p(int q, int r); // p is a function type int(int, int) p f { return q + r; } // Error
在 C89 中,specifiers-and-qualifiers 是可选的,如果省略,函数的返回类型默认为int(可能由declarator修改)。 此外,旧式定义不需要为declaration-list中的每个参数提供声明。任何缺少声明的参数都具有int类型 max(a, b) // a and b have type int, return type is int { return a>b?a:b; } |
(直到 C99) |
[编辑] 缺陷报告
以下行为改变的缺陷报告被追溯地应用于以前发布的 C 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
DR 423 | C89 | 返回类型可能受限 | 返回类型隐式解除限定 |
[编辑] 参考
- C17 标准 (ISO/IEC 9899:2018)
- 6.9.1 函数定义 (p: 113-115)
- C11 标准 (ISO/IEC 9899:2011)
- 6.9.1 函数定义 (p: 156-158)
- C99 标准 (ISO/IEC 9899:1999)
- 6.9.1 函数定义 (p: 141-143)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 3.7.1 函数定义
[编辑] 另请参阅
C++ 文档,关于函数定义
|