函数定义

来自cppreference.com
< c‎ | language

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

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

specifiers-and-qualifiers parameter-list-declarator function-body (1)
specifiers-and-qualifiers identifier-list-declarator declaration-list function-body (2)

其中

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

解释

函数声明,函数的返回类型由 specifiers-and-qualifiers 中的类型指定符确定,并像在声明中一样可以由 declarator 修改。返回类型必须是完整的非数组对象类型或 void 类型。

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 限定,则为构造函数类型的目的,将它调整到其无限定版本。

(C17 起)

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

不同于函数声明,不允许无名形参,即使不在函数中使用也必须命名它们。仅有的例外是参数列表 (void)

int f(int, int); // 声明
// int f(int, int) { return 7; } // 错误
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__

在每个 function-body 内,拥有块作用域和静态存储期的预定义变量 __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 中, specifiers-and-qualifiers 是可选的,若省略它,则函数返回类型默认为 int (可由 declarator 修改)。

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

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

引用

  • C11 standard (ISO/IEC 9899:2011):
  • 6.9.1 Function definitions (p: 156-158)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.9.1 Function definitions (p: 141-143)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.7.1 Function definitions

参阅