6.9.1 函数定义

语法

1、function-definition:

declaration-specifiers    declarator    declaration-listopt    compound-statement

declaration-list:

declaration

declaration-list    declaration

约束

2、在一个函数定义中所声明的标识符(它是函数名)应该是一个函数类型,它通过函数定义的声明符部分指定。[注:这样的目的是在一个函数定义中的类型类别不能从一个typedef继承:

typedef int F(void);    // 类型F是一个“返回int,不带有形参的函数”
F f, g; // f和g都具有与F相兼容的类型
F f { /* ... */ } // 错误:语法/约束错误
F g() { /* ... */ } // 错误:将g声明为返回一个函数
int f(void) { /* ... */ } // 正确:f具有与F相兼容的类型
int g() { /* ... */ } // 正确:g具有与F相兼容的类型
F *e(void) { /* ... */ } // e返回指向一个函数的指针
F *((e))(void) { /* ... */ } // 与上述相同,不用去管圆括号
int (*fp)(void); // fp指向具有类型F的一个函数
F *fp; // fp指向一个具有类型F的函数

3、一个函数的返回类型应该是void或一个完整的对象类型,但不能是数组类型。

4、如果存在存储类说明符,那么在声明说明符中应该要么是extern,要么是static

5、如果声明符包含一个形参类型列表,那么每个形参的声明应该包含一个标识符,除了一个形参列表由一单个void类型形参构成的特殊情况,在这种情况下,不应该有一个标识符。后面不应该跟着任何声明列表。

6、如果声明符包含了一个标识符列表,那么在声明列表中的每个声明应该至少具有一个声明符,那些声明符应该尽从声明列表声明标识符,并且标识符列表中的每个标识符应该被声明。被声明为一个typedef名的一个标识符不应该重新声明为一个形参。在声明列表中的声明不应该包含除了register之外的其它存储类说明符,并且不能包含初始化。

语义

7、一个函数定义中的声明符指定了正被定义的函数名以及其形参标识符。如果声明符包含一个形参类型列表,那么该列表也指定了所有形参的类型;这么一个声明符也担任一个函数原型为稍后对同一函数的调用,在同一翻译单元中。如果声明符包含了一个标识符列表,[注:见“未来语言方向”(6.11.7)。]形参的类型应该在后续声明列表中被声明。在任何一种情况下,一个形参类型列表的每个形参的类型被调整为6.7.6.3中描述的;结果类型应该是一个完整的对象类型。

8、如果接受一可变数量实参的函数定义时没有一个用省略号记号结尾的形参类型列表,那么行为是未定义的。

9、每个形参具有自动存储周期;其标识符是一个左值。[注:一个形参标识符不能在函数体内被重新声明,除了在一个封闭的语句块内。]形参存储的布局是未定义的。

10、在函数入口处,每个可变修改的形参的size表达式都被计算,并且每个实参表达式的值被转换为相应形参的类型,就好比是一个赋值操作。(作为实参的数组表达式与函数指派符在调用之前被转换为指针。)

11、在所有形参被赋值之后,由函数定义体所构成的复合语句被执行。

12、如果终结一个函数的}到达,那么行为是未定义的。

13、例1 在下列代码中:

extern int max(int a, int b)
{
return a > b ? a : b;
}

extern是存储类说明符,而int是类型说明符;max(int a, int b)是函数声明符;{ return a > b ? a : b; } 是函数体。以下类似的定义使用了标识符列表形式给形参声明:

extern int max(a, b)
int a, b;
{
return a > b ? a : b;
}

这里int a, b;是形参的声明列表。这两个定义的不同之处是第一种形式扮演了一个原型声明,它迫使后续对此函数的调用对实参类型进行转换,而第二种形式则不然。

14、例2 为了将一个函数传递给另一个,有人会说

int f(void);
/* ... */
g(f);

然后对g的定义可能写作

void g(int (*funcp)(void))
{
/* ... */
(*funcp)(); /* 或funcp(); ... */
}

或者等价地

void g(int func(void))
{
/* ... */
func(); /* 或(*func)(); ... */
}

本结完。

ISO/IEC 9899:2011 条款6.9.1——函数定义的更多相关文章

  1. ISO/IEC 9899:2011 条款6.7.8——类型定义

    6.7.8 类型定义 语法 1.typedef-name: identifier 约束 2.一个typedef名指定了一个可变修改的类型,然后它应该具有语句块作用域. 语义 3.在一个声明中,该声明的 ...

  2. ISO/IEC 9899:2011 条款6.7.4——函数说明符

    6.7.4 函数说明符 语法 1.function-specifier: inline _Noreturn 约束 2.函数说明符应该只能被用在对一个函数标识符的声明中. 3.对一个含有外部连接函数的内 ...

  3. ISO/IEC 9899:2011 条款3——术语、定义与符号

    3. 术语.定义与符号 1.对于此国际标准的意图,应用了以下定义.其它术语是在用斜体类型或一个语法规则左侧出现的地方定义.在本国际标准中所显式定义的术语不被假定为对其它地方所定义的类似术语的隐式引用. ...

  4. ISO/IEC 9899:2011 条款5——5.2.1 字符集

    5.2.1 字符集 1.两个字符集和它们相关联的依次顺序应该被定义:写在源文件中的集合(源字符集),以及在执行环境中被解释的集合(执行字符集).每个集合此外被划分为一个基本字符集,其内容由本子条款给出 ...

  5. ISO/IEC 9899:2011 条款6.4.2——标识符

    6.4.2 标识符 6.4.2.1 通用 语法 1.identifier: identifier-nodigit identifier    identifier-nondigit identifie ...

  6. ISO/IEC 9899:2011 条款6.4.3——通用字符名

    6.4.3 通用字符名 语法 1.通用字符名: universal_character-name: \u hex-quad(四位十六进制数) \U hex-quad hex-quad hex-quad ...

  7. ISO/IEC 9899:2011 条款6.7.6——声明符

    6.7.6 声明符 语法 1.declarator: pointeropt    direct-declarator direct-declarator: identifier (    declar ...

  8. ISO/IEC 9899:2011 条款6.7.3——类型限定符

    6.7.3 类型限定符 语法 1.type-qualifier: const restrict volatile _Atomic 约束 2.除了指针类型(其被引用的类型是一个对象类型)之外的类型,不应 ...

  9. ISO/IEC 9899:2011 条款5——5.2.4 环境限制

    5.2.4 环境限制 1.翻译与执行环境都约束了语言翻译器和库的实现.下面概述了对一个顺应标准实现的语言相关的环境限制:库相关的限制在条款7中讨论. 5.2.4.1 翻译限制 1.实现应该能够翻译并执 ...

随机推荐

  1. Vue钩子函数

    Vue的生命周期函数 beforeCreate:function(){ console.log('1-beforeCreate 初始化之后'); }, created:function(){ cons ...

  2. PHP——封装Curl请求方法支持POST | DELETE | GET | PUT 等

    前言 Curl:  https://www.php.net/manual/en/book.curl.php curl_setopt: https://www.php.net/manual/en/fun ...

  3. go语言-二进制与位运算

    一.进制介绍 1.二进制:0,1 -->不能直接用二进制来表示一个整数,用%b输出二进制 package mainimport "fmt"func main() { var ...

  4. 如何轻松愉快地理解条件随机场(CRF)

    https://blog.csdn.net/DCX_abc/article/details/78319246 机器学习之条件随机场(CRF): https://blog.csdn.net/wangya ...

  5. php获取时期时间信息函数

    在正式学习日期函数前大家得了解几个概念: 1.时区 2.世界时 3.unix时间戳 时区 这个概念,之前大家听说过很多.我们来啰嗦两句,我们现实生活中使用的实区,在电脑里面也是一样有规定的.大理石机械 ...

  6. 繁繁的游戏 Floyd

    繁繁的游戏 Floyd 繁繁想和小伙伴们打游戏,游戏在一个山庄进行,这个山庄有N座山,编号为\(1\)到\(N\),为了方便大 家在不同的山之间移动,繁繁建了一些桥,由于技术的原因,桥连接的两座山的高 ...

  7. codevs1580单词游戏

    题目描述中说: 单词为at,k=8则新单词为ib 推移规则是:如果k为正数则下推,否则上推,当推移超越边界时回到另一端继续推移. 但在我做题时发现: 这个描述与数据所要求的是完全相反的!!!! 样例1 ...

  8. 2017.10.1 国庆清北 D1T2 两个逗比捉迷藏

    题目描述 你是能看到第二题的friends呢. ——laekov Hja和Yjq在玩捉迷藏.Yjq躲了起来,Hja要找他.在他们玩游戏的房间里,只有一堵不透明的墙和一个双面的镜子.Hja和Yjq可以看 ...

  9. [golang]Go内嵌静态资源go-bindata的安装及使用

    使用 Go 开发应用的时候,有时会遇到需要读取静态资源的情况.比如开发 Web 应用,程序需要加载模板文件生成输出的 HTML.在程序部署的时候,除了发布应用可执行文件外,还需要发布依赖的静态资源文件 ...

  10. 判断是否是合法的IP地址

    ipv4 import re #简单的匹配给定的字符串是否是ip地址,下面的例子它不是IPv4的地址,但是它满足正则表达式 if re.match(r"^(?:[0-9]{1,3}\.){3 ...