函数定义

来自cppreference.com
< c‎ | language

函数定义将函数体(声明与语句的序列)与函数名及参数列表关联。不同于函数声明,函数定义只允许在文件作用域(不存在嵌套函数)。

C 支持二种函数定义的形式:

属性说明符序列(可选) 说明符与限定符 形参列表声明符 函数体 (1)
说明符与限定符 标识符列表声明符 声明列表 函数体 (2) (C23 前)

其中

属性说明符序列 - (C23)可选的属性列表,应用到函数
说明符与限定符 - 下列的组合
形参列表声明符 - 参数列表指代函数参数的函数类型的声明器
标识符列表声明符 - 标识符列表指代函数参数的函数类型的声明器
声明列表 - 标识符列表声明符 中声明每个参数的声明序列。这些声明不能使用初始化器,而且仅允许 register 作为存储类说明符
函数体 - 复合语句,是花括号所包括的声明及语句序列,只要调用此函数就会被执行
1) 新式 (C89) 函数定义。此定义引入函数自身,并为任何将来的函数调用表达式提供函数原型,强迫从实参表达式转换到声明形参类型。
int max(int a, int b)
{
    return a>b?a:b;
}
 
double g(void)
{
    return 0.1;
}
2) (C23 前) 旧式 (K&R) 函数定义。此定义不表现为原型,而任何将来的函数调用表达式将进行默认参数提升。
int max(a, b)
int a, b;
{
    return a>b?a:b;
}
double g()
{
    return 0.1;
}

解释

函数声明,函数的返回类型由 说明符与限定符 中的类型说明符确定,并像在声明中一样可以由 声明符 修改。返回类型必须是完整的非数组对象类型或 void 类型。若返回类型会有 cvr 限定,则为构造函数类型的目的,将它调整为其无限定版本。

void f(char *s) { puts(s); } // 返回类型为 void
int sum(int a, int b) { return a+b: } // 返回类型为int
int (*foo(const void *p))[3] { // 返回类型是指向 3 个 int 的数组的指针
    return malloc(sizeof(int[3]));
}

函数声明,为构造函数类型的目的,将参数类型从函数调整到指针,从数组调整到指针,并且为确定兼容函数类型的目的,忽略所有参数类型的顶层 cvr 限定符。

不同于函数声明,不允许无名形参(否则旧式 (K&R) 函数定义中会有冲突),即使不在函数中使用也必须命名它们。仅有的例外是参数列表 (void)

(C23 前)

函数定义中形参可以为无名,因为旧式 (K&R) 函数定义已被移除。函数体内不能以名称访问无名形参。

(C23 起)
int f(int, int); // 声明
// int f(int, int) { return 7; } // C23 前错误, C23 起 OK
int f(int a, int b) { return 7; } // 定义
int g(void) { return 8; } // OK : void 不声明参数

在函数体内,每个具名参数都是左值表达式,它们拥有自动存储期块作用域。参数在内存中的布局(或者它们究竟是否存储于内存中)是未指定的:这是调用约定的一部分。

int main(int ac, char **av)
{
    ac = 2; // 参数是左值
    av = (char *[]){"abc", "def", NULL};
    f(ac, av);
}

函数调用机制上的其他细节见函数调用运算符,关于从函数返回,见 return

__func__

在每个 函数体 内,拥有块作用域和静态存储期的预定义变量 __func__ 可用,它如同立即通过以下方式在开花括号后定义:

static const char __func__[] = "function name";

此特殊标识符有时与预定义宏常量 __FILE____LINE__ 结合使用,例如为 assert 所用。

(C99 起)

注解

参数列表必须显式存在于声明器中,不能从 typedef 继承它

typedef int p(int q, int r); // p 是类型为 int(int, int) 的函数
p f { return q + r; } // 错误

C89 中, 说明符与限定符 是可选的,若省略它,则函数返回类型默认为 int (可由 声明符 修改)。

另外,旧式定义不要求在 声明列表 中声明每个参数。任何缺少声明的参数拥有 int 类型

max(a, b) // a 和 b 拥有 int 类型,返回类型为 int
{
    return a>b?a:b;
}
(C99 前)

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C 标准。

缺陷报告 应用于 出版时的行为 正确行为
DR 423 C89 返回类型可以有限定 返回类型被隐式除去限定

引用

  • C17 标准(ISO/IEC 9899:2018):
  • 6.9.1 Function definitions (第 113-115 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 6.9.1 Function definitions (第 156-158 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 6.9.1 Function definitions (第 141-143 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 3.7.1 Function definitions

参阅