【C语言】学习笔记 第9章 函数 9.7 泛型选择 比眉伴天荒 2024-03-22 10:19 28阅读 0赞 ### 【C语言】学习笔记 ### #### 文章目录 #### * * 【C语言】学习笔记 * * 第9章 函数 * * 9.7 泛型选择 #### 第9章 函数 #### ![在这里插入图片描述][0b8b3c7d7732469e87b8a03be8dfc566.png_pic_center] 函数是 C 程序的构建块。每个函数本质上是一个自带声明和语句的小程序。可以利用函数 把程序划分成小块,这样便于人们理解和修改程序。由于不必重复编写要多次使用的代码,函 数可以使编程不那么单调乏味。此外,函数可以复用:一个函数最初可能是某个程序的一部分, 但可以将其用于其他程序。 ##### 9.7 泛型选择 ##### 有时候你可能希望用同一个名字编写好几个函数,因为它们实现类似的功能,只是参数和 返回类型不同。这在其他一些高级语言(比如 C++)里很容易,因为它们提供**函数重载**,但 C 语言不支持这种做法。 实际上,C 标准库已经用了这种手段。从 C99 开始,C 标准库用泛型宏来统一 数学函数的各个版本。 比如对于正弦函数,为了应对 `double`、`float`、`long double`、`double _Complex`、`float _Complex` 和 `long double _Complex` 这些类型的参数,标准库定义了相应 的函数:`sin`、`sinf`、`sinl`、`csin`、`csinf` 和 `csinl`。有了泛型宏之后,我们可以直接用 sin 来调用它们而不必关心调用的实际上是哪个版本,因为泛型宏可以根据我们传入的参数找到对 应的版本。 问题在于,虽然 C99 的标准库使用了这项技术,但并没有在语言(语法)层面上提供任何 支持。为了从语言层面上解决这种需求,从 `C11` 开始,C 标准引入了泛型选择(generic selection), 它是一个表达式,其语法为 _Generic( 表达式 , 泛型关联列表 ) 这里,泛型关联列表由一个或多个泛型关联组成,如果泛型关联多于一个,则它们之间用逗号 “`,`”分隔。泛型关联的语法为 类型名 : 表达式 default : 表达式 泛型选择是基本表达式,它在程序翻译期间求值,其主要目的是从多个备选的表达式中挑 出一个作为结果。泛型选择表达式的类型就是被挑选出的那个表达式的类型;泛型选择表达式 的值取决于被挑选出的那个表达式的值。下面通过一个实例来解释泛型选择表达式的功能。 # include <stdio.h> # include <math.h> # include <complex.h> # define sin(x) _Generic(x, float:sinf, double:sin, long double:sinl, float _Complex:csinf, double _Complex:csin, long double _Complex:csinl)(x) int main(void) { printf("%f\n", sin(.5f)); // S double _Complex d = sin(.3+.5i); printf("%.2f%+.2f*I", creal (d), cimag (d)); return 0; } 在以上代码中,标识符 sin 被定义为宏,虽然在头文件 里也声明了一个同名的 函数,但预处理器会先将它识别为宏名并做宏替换。另外,虽然我们在这里将泛型选择表达式 定义为宏体,但泛型选择表达式和宏没有任何关系,这个例子有其特殊性:**我们是希望用同一 个宏名 sin 来应付不同类型的操作数,并依靠泛型选择表达式解析出与此操作数的类型相匹配 的库函数.** 以语句 S 为例,在预处理期间,C 实现将其展开为 printf("%f\n", _Generic(.5f, float:sinf, double:sin, long double:sinl, float _Complex:csinf, double _Complex:csin, long double _Complex:csinl) (x)); 在泛型选择表达式中,第一个表达式称为控制表达式(上例中的`.5f`),它并不求值,C 实 现只提取它的类型信息。接着,如果某个泛型关联中的类型名和控制表达式的类型兼容(匹配), 则泛型选择的结果表达式就是该泛型关联中的表达式。 在上例中,表达式`.5f` 的类型是 `float`,则最终选择的是表达式 `sinf`。这就是说,在程序 翻译期间,上述语句进一步被简化为以下等价形式: printf("%f\n", sinf(x)); 此外,在同一个泛型选择中,不允许两个或多个泛型关联的类型名所指定的类型互相兼容。 换句话说,不允许控制表达式匹配多个泛型关联的类型名。 如果需要,可以使用一个 default 泛型关联。它的价值在于,如果控制表达式的类型和任何一个泛型关联的类型名所指定的类型都不兼容(匹配),则自动选择 default 泛型关联中的 表达式。但是,一个泛型选择中只允许有一个 default 泛型关联。 要特别注意的是,\*\*泛型选择不能识别数组类型,\*\*因为数组类型的表达式会被转换为指向其 首元素的指针。 [0b8b3c7d7732469e87b8a03be8dfc566.png_pic_center]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/22/6ee607ef085a43cd9d96e713c7b26bbe.png
相关 【C语言】学习笔记 第9章 函数 编程题 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 编程题 第9章 函数 ![在这里 今天药忘吃喽~/ 2024年03月22日 10:19/ 0 赞/ 38 阅读
相关 【C语言】学习笔记 第9章 函数 9.7 泛型选择 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.7 泛型选择 第9章 函数 比眉伴天荒/ 2024年03月22日 10:19/ 0 赞/ 29 阅读
相关 【C语言】学习笔记 第9章 函数 9.6 递归 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.6 递归 布满荆棘的人生/ 2024年03月22日 10:19/ 0 赞/ 79 阅读
相关 【C语言】学习笔记 第9章 函数 9.4 return语句 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.4 return语句 第9章 函 港控/mmm°/ 2024年03月22日 10:18/ 0 赞/ 42 阅读
相关 【C语言】学习笔记 第9章 函数 9.5 程序终止 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.5 程序终止 我就是我/ 2024年03月22日 10:18/ 0 赞/ 34 阅读
相关 【C语言】学习笔记 第9章 函数 9.3 实际参数 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.3 实际参数 喜欢ヅ旅行/ 2024年03月22日 10:18/ 0 赞/ 59 阅读
相关 【C语言】学习笔记 第9章 函数 9.2 函数声明 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.2 函数声明 第9章 函数 一时失言乱红尘/ 2024年03月22日 10:18/ 0 赞/ 36 阅读
相关 【C语言】学习笔记 第9章 函数 9.1 函数的定义和调用 【C语言】学习笔记 文章目录 【C语言】学习笔记 第9章 函数 9.1 函数的定义和调用 你的名字/ 2024年03月22日 10:17/ 0 赞/ 42 阅读
相关 【C语言】学习笔记 第5章 选择语句 编程题 【C语言】学习笔记 文章目录 【C语言】学习笔记 第5章 选择语句 编程题 第5章 选择语句 ! 布满荆棘的人生/ 2024年03月22日 08:43/ 0 赞/ 64 阅读
相关 C++学习——第9章 函数 1 函数的重载 利用函数的重载,可以在一个程序中使用同名的若干个函数。主要的限制是给定名称的每个函数必须有不同的参数列表。 如果满足下列条件之一,两个同名函数就是不同的: 清疚/ 2022年04月13日 10:12/ 0 赞/ 351 阅读
还没有评论,来说两句吧...