首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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中声明每个标识符的声明序列。这些声明不能使用初始化器,唯一允许的存储类说明符是寄存器。

功能体

-

一个复合语句,它是一个括号括起来的声明和语句序列,每当调用该函数时都会执行

  • 可能由声明者修改的类型说明符构成返回类型
  • 存储类说明符,其中确定所述识别符的键(staticextern或无)
  • 函数说明符inline,noreturn或none
代码语言:txt
复制
 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)功能定义。该定义既引入了函数本身,又作为未来函数调用表达式的函数原型,强制从参数表达式转换为声明的参数类型。

代码语言:javascript
复制
int max(int a, int b)
{
    return a>b?a:b;
}
 
double g(void)
{
    return 0.1;
}

2)旧式(K&R)功能定义。这个定义不像原型,任何未来的函数调用表达式都会执行默认参数促销。

代码语言:javascript
复制
int max(a, b)
int a, b;
{
    return a>b?a:b;
}
double g()
{
    return 0.1;
}

说明

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

代码语言:javascript
复制
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)

代码语言:javascript
复制
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

在函数体内,每个参数都是一个左值表达式,它们具有自动存储持续时间和块范围。内存中的参数布局(或者如果它们存储在内存中)未指定:它是调用约定的一部分。

代码语言:javascript
复制
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 继承。

代码语言:javascript
复制
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):
    • 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

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com