C语言之_Generic用法实例(九十一)

2024-04-14 06:52

本文主要是介绍C语言之_Generic用法实例(九十一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2._Generic介绍
    • 🌻3.代码实例
      • 🐓3.1 简单的类型选择
      • 🐓3.2 类型转换宏
      • 🐓3.3 泛型函数

🌻1.前言

本篇目的:C语言之_Generic用法实例

🌻2._Generic介绍

  • C语言的_Generic表达式是C11标准引入的一个特性,它提供了一种在编译时基于表达式类型选择函数或值的方法。这种机制与C++中的模板元编程相似,但更为简单和受限。
  • _Generic表达式的基本形式如下:
_Generic(expr, type1: value1, type2: value2, ..., default: default_value)
  • 其中expr是我们要判断的表达式,type1, type2, ...是可能的类型,value1, value2, ...是对应的类型为真时返回的值,default_value是默认返回的值(当没有任何类型匹配时)。
  • _Generic表达式的基本思想是,根据expr的类型,从多个候选值中选择一个。这种选择是在编译时进行的,因此_Generic表达式是一种编译时多态。
  • _Generic表达式可以用于多种场景,比如根据不同的类型选择不同的处理函数,实现类型转换等。它的一个重要特点是,它仅适用于类型,而不是特定的值。因此,我们不能用它来做数值的比较或者复杂的类型检查。此外,__Generic表达式在编译时求值,因此它不能用于运行时类型检查。
  • 在使用_Generic表达式时,我们需要注意的是,它的类型匹配是基于expr的静态类型,而不是它的实际值。这意味着,如果expr是一个指针,那么_Generic表达式将根据指针的类型进行匹配,而不是指针指向的对象的类型。
  • 此外,_Generic表达式的类型匹配是按照它在表达式中的顺序进行的。如果多个类型匹配expr,那么将选择第一个匹配的类型。因此,我们在编写_Generic表达式时,应该将最具体的类型放在前面,将最一般的类型放在后面。
  • _Generic表达式的一个常见用途是实现泛型宏。在C语言中,宏是类型无关的,这意味着我们不能编写一个宏,它可以接受任何类型的参数并正确地进行类型转换。但是,通过使用_Generic表达式,我们可以编写一个宏,它在编译时根据参数的类型选择正确的表达式。
  • 总的来说,_Generic表达式为C语言提供了一种简单的、编译时的类型选择机制。尽管它的功能有限,但在某些情况下,它仍然能够提供便利和代码的清晰度。

🌻3.代码实例

🐓3.1 简单的类型选择

#include <stdio.h>void print_int(int i) {printf("Integer: %d\n", i);
}void print_float(float f) {printf("Float: %f\n", f);
}void print_char(char c) {printf("Char: %c\n", c);
}void generic_print(void *data) {_Generic(data, int: print_int,float: print_float,char: print_char)(data);
}int main() {int i = 42;float f = 3.14f;char c = 'A';generic_print(&i);generic_print(&f);generic_print(&c);return 0;
}

🐓3.2 类型转换宏

#include <stdio.h>#define TO_INT(x) _Generic((x), \int: (x), \float: (int)(x), \default: (int)(x))int main() {int i = 42;float f = 3.14f;char c = 'A';printf("ToInt of i: %d\n", TO_INT(i));printf("ToInt of f: %d\n", TO_INT(f));printf("ToInt of c: %d\n", TO_INT(c));return 0;
}

🐓3.3 泛型函数

#include <stdio.h>#define ADD(x, y) _Generic((x), \int: _Generic((y), \int: (x) + (y), \default: (x) + (int)(y)), \float: _Generic((y), \float: (x) + (y), \default: (x) + (float)(y)), \default: _Generic((y), \default: (int)(x) + (int)(y)) \)int main() {int i = 42;float f = 3.14f;char c = 'A';printf("ADD(i, i): %d\n", ADD(i, i));printf("ADD(f, f): %f\n", ADD(f, f));printf("ADD(i, f): %f\n", ADD(i, f));printf("ADD(c, i): %d\n", ADD(c, i));return 0;
}

这篇关于C语言之_Generic用法实例(九十一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902360

相关文章

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Springboot中Jackson用法详解

《Springboot中Jackson用法详解》Springboot自带默认json解析Jackson,可以在不引入其他json解析包情况下,解析json字段,下面我们就来聊聊Springboot中J... 目录前言Jackson用法将对象解析为json字符串将json解析为对象将json文件转换为json

MySQL的索引失效的原因实例及解决方案

《MySQL的索引失效的原因实例及解决方案》这篇文章主要讨论了MySQL索引失效的常见原因及其解决方案,它涵盖了数据类型不匹配、隐式转换、函数或表达式、范围查询、LIKE查询、OR条件、全表扫描、索引... 目录1. 数据类型不匹配2. 隐式转换3. 函数或表达式4. 范围查询之后的列5. like 查询6

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

bytes.split的用法和注意事项

当然,我很乐意详细介绍 bytes.Split 的用法和注意事项。这个函数是 Go 标准库中 bytes 包的一个重要组成部分,用于分割字节切片。 基本用法 bytes.Split 的函数签名如下: func Split(s, sep []byte) [][]byte s 是要分割的字节切片sep 是用作分隔符的字节切片返回值是一个二维字节切片,包含分割后的结果 基本使用示例: pa