C
C 语法

Function definitions

函数定义

函数定义将函数体(声明和语句序列)与函数名称和参数列表关联起来。与函数声明不同,函数定义只允许在文件范围内(没有嵌套函数)。

C支持两种不同形式的函数定义:

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

其中

符和限定符-类型说明符的组合,可能被声明器修改,形成返回类型存储类说明符,它确定标识符(静态,外部或无)与inline,noreturn或none
参数列表说明符-一个函数类型的声明符,它使用参数列表来指定函数参数
标识符列表说明符-一个函数类型的声明符,它使用标识符列表来指定函数参数
声明列表-在identifier-list-declarator中声明每个标识符的声明序列。这些声明不能使用初始化器,唯一允许的存储类说明符是寄存器。
功能体-一个复合语句,它是一个括号括起来的声明和语句序列,每当调用该函数时都会执行

  • 可能由声明者修改的类型说明符构成返回类型

parameter-list-declarator - a declarator for a function type which uses a [parameter list](function_declaration) to designate function parameters identifier-list-declarator - a declarator for a function type which uses a [identifier list](function_declaration) to designate function parameters declaration-list - sequence of declarations that declare every identifier in identifier-list-declarator. These declarations cannot use initializers and the only [storage-class specifier](storage_duration) allowed is `register`. function-body - a [compound statement](statements#Compound_statements), that is a brace-enclosed sequence of declarations and statements, that is executed whenever this function is called

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; }

说明

与函数声明一样,函数的返回类型由声明符中的类型说明符确定,并可能在声明中像通常一样由声明器修改,这些类型必须是完整的非数组对象类型或类型void

void f(char *s) { puts(s } // return type is void int sum(int a, int b) { return a+b: } // return type is int int (*foo(const void *p))[3] { // return type is pointer to array of 3 int return malloc(sizeof(int[3]) }

和函数声明一样,参数的类型从函数调整到指针,从数组到指针,为了构造函数类型,它们的顶级限定符被去除。

与函数声明不同,未命名的形式参数是不允许的,即使它们没有在函数中使用,它们也必须被命名。唯一的例外是特殊参数列表(void)

int f(int, int // declaration // int f(int, int) { return 7; } // Error 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 }

有关函数调用机制的其他详细信息,请参阅函数调用运算符,然后从函数返回。

__func__在每个函数体中,可以使用具有块范围和静态存储持续时间的特殊预定义变量__func__,就像在紧跟在大括号之后定义的那样。static const char __func __ [] =“function name”; 这个特殊的标识符有时与预定义的宏常量__FILE__和__LINE__结合使用,例如通过assert。(自C99以来)

笔记

参数列表必须明确地出现在声明器中,它不能从 typedef 继承。

typedef int p(int q, int r // p is a function type int(int, int) p f { return q + r; } // Error

在C89中,说明符和限定符是可选的,如果省略,函数的返回类型默认为int(可能由声明者修改)。另外,旧式定义不需要声明列表中的每个参数。任何声明缺失的参数都有int类型。max(a,b)// a和b的类型是int,返回类型是int {return a> b?a:b; }(直到C99)

参考

  • C11 standard (ISO/IEC 9899:2011):