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. Integer Inquiry UVA-424(大整数)

    题意分析: 将字符串倒着存入int数组中,每次加完后再取余除去大于10的部分 关键:倒着存入,这样会明显缩短代码量. #include<iostream> #include<cstd ...

  2. Java内存模型中volatile关键字的作用

    volatile作用总结: 1. 强制线程从公共内存中取得变量的值,而不是从线程的私有的本地内存中,volatile修饰的变量不具有原子性(修改一个变量的值不能同步). 2. 保证volatile修饰 ...

  3. qingqing的项目

    1 https://www.cnblogs.com/zhangqing979797/p/10147679.html 2 https://www.cnblogs.com/zhangqing979797/ ...

  4. 51nod 2486 小b和矩阵

    小b有一个m行n列的矩阵. 她会从(1,1)开始,顺时针螺旋访问该矩阵,每个元素恰好被访问一次. 请你按小b的访问顺序输出每个元素. 收起   输入 第一行输入两个数m和n,其中0<m,n≤50 ...

  5. 题解 洛谷P4302 【[SCOI2003]字符串折叠】

    一眼区间\(dp\),但蒟蒻的我还是调了好久\(qwq\) [状态设置] 设\(f[i][j]\)为子串\([i,j]\)的最短折叠 最后答案为\(f[1][n]\) 废话 [初始化] \(1\) 首 ...

  6. 题解 UVa10943

    题目大意 多组数据,每组数据给定两个整数 \(n,k\),求出用 \(k\) 个不超过 \(n\) 的数相加得到 \(n\) 的方案数(不同顺序不算同种). 分析 计数水题.令 \(f_{i,j}\) ...

  7. mysql跨表删除多条记录

    Mysql可以在一个sql语句中同时删除多表记录,也可以根据多个表之间的关系来删除某一个表中的记录. 假定我们有两张表:Product表和ProductPrice表.前者存在Product的基本信息, ...

  8. 015——C#软件出现《未在本地计算机上注册"Microsoft.Jet.OLEDB.4.0"》

    (一)参考文献:https://zhidao.baidu.com/question/361243661437448812.html https://blog.csdn.net/yyx3214/arti ...

  9. C# winform Panel 添加 滚动条

    Detailed discussion here. Try this instead for 'only' scrolling vertical.(auto scroll needs to be fa ...

  10. C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置

    #include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7, ...