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. Linux中rpm命令用法

    rpm -ivh 软件包名 安装软件包并显示安装进度.这个是用得最多的了. rpm -qa 查询已经安装哪些软件包. rpm -q 软件包名 查询指定软件包是否已经安装. rpm -Uvh  软件包名 ...

  2. python3 tkinter模块

    一.tkinter 1.tkinter--tool kit interface工具包接口,用于GUI(Graphical User Interface)用户图形界面, 2.python3.x把Tkin ...

  3. djangCrm

    ---恢复内容开始--- 一> 在数据库进行循环取多对多 def get_classlist(self): l=[] for cls in self.class_list.all(): l.ap ...

  4. Linux 服务器性能出问题,排查下这些参数指标

    taozj马哥Linux运维 一个基于 Linux 操作系统的服务器运行的同时,也会表征出各种各样参数信息.通常来说运维人员.系统管理员会对这些数据会极为敏感,但是这些参数对于开发者来说也十分重要,尤 ...

  5. unsupervised learning: K-means 算法

    k-means算法是目前最流行的,用得最多的一种clustering算法 K-means算法 如果我们想要将上图中的绿色的点分为两类,首先随机的选取两个cluster centroids(聚类中心), ...

  6. String 堆内存和栈内存

    java把内存划分为两种:一种是栈(stack)内存,一种是堆(heap)内存 在函数中定义的一些基本类型的变量和对象的引用变量都在栈内存中分配,当在一段代码块定义一个变量时,java就在栈中为这个变 ...

  7. 从零实现jQuery的extend

    前言 jQuery 的 extend 是 jQuery 中应用非常多的一个函数,今天我们一边看 jQuery 的 extend 的特性,一边实现一个 extend! extend 基本用法 先来看看 ...

  8. RCNN,Fast RCNN,Faster RCNN 的前生今世:(2) R- CNN (3,2,1)

    3.三次IOU  2.2次model run  1,一次深度神经网络 rcnn主要作用就是用于物体检测,就是首先通过selective search 选择2000个候选区域,这些区域中有我们需要的所对 ...

  9. netty: marshalling传递对象,传输附件GzipUtils

    netty: marshalling传递对象,传输附件GzipUtils 前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化.可以使用java进行对象序列化,netty去传输,但ja ...

  10. .net使用WebUploader做大文件的分块和断点续传

    ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现. 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压. ASP.NE ...