当前位置: 首页 > news >正文

书摘:C 嵌入式系统设计模式 04

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。

本系列描述我对书中内容的理解。

  1. 实现类的最简单方法是使用文件作为封装边界:公共变量和函数声明在 .h 文件中,函数实现和私有变量在 .c 文件中。
  2. 一种更灵活的方法是使用文件中的结构体表示类。与结构体位于同一文件中的函数定义类的操作。为了确保函数能够访问正确的对象数据,我们需要传入一个 me 指针。
  3. 在结构体本身中嵌入函数指针,这可以实现子类的继承。

以上就是本书中用 C 语言模拟类的三种方法。这三种方法复杂度逐渐增加,不要因为第一种方法简单就认为它用处不大,不是这样的。实际上,这三种方法在 C 编程中都十分常用,尤其在编写模块化程序时,它们甚至与类无关,只是恰好可以模拟类的行为。

这三种方法都以文件作为封装边界,只是后两种没有明确指出。封装的目的在于降低整体复杂度。在编程界,封装是一种重要的思想。《UNIX 哲学》告诉我们:“要编制复杂软件而又不至于一败涂地的唯一方法就是降低其整体复杂度——用清晰的接口把若干简单的模块组合成一个复杂软件。如此一来,多数问题只会局限于某个局部,那么就还有希望对局部进行改动而不至牵动全身。”

第 1 种方法中将公共变量声明在 .h 文件,我自己并不认同这种方法,我推荐使用函数封装全局变量,对外只提供函数,这实际上对外隐藏了数据,因此封装性更好。此外,这样更灵活,有利于以后的扩展。这怎么理解呢?用函数封装一下后,函数能做的事情,比使用变量要多的多,你可以在函数中轻松的修改或扩展功能,而无需修改使用该函数(原来这里是变量)的所有代码

许久之前,我认为这样影响效率。直到我意识到,我手上的这颗 M3 芯片,1ms 可以执行110000 条单周期指令,或者换句话,1ms 可以执行 220KB 的代码。现代的单片机速度今非昔比了,效率固然重要,但可扩展性有些时候更重要。何况,对现代的编译器来说,用函数封装变量,真的会影响效率吗?还真不一定。

对于第一种方法,我并不赞同将公共变量声明在 .h 文件中。我主张使用函数来封装全局变量,仅对外提供函数接口。这样能更好地隐藏数据,从而提高封装性。此外,这种做法更灵活,有利于未来的扩展。这怎么理解呢?使用函数封装后,函数能做的事情,比变量要多的多。你可以在函数内部轻松地修改或扩展功能,而无需修改使用该函数的所有代码。

许久之前,我认为这样影响效率。直到我意识到,我手上的这颗 M3 芯片,1ms 可以执行110000 条单周期指令,或者换句话,1ms 可以执行 220KB 的代码。时至今日,单片机的速度今非昔比了!效率固然重要,但可扩展性有些时候更重要。何况,对现代的编译器来说,用函数封装变量,真的会影响效率吗?还真不一定。

在标准 C 编程中,复杂的算法仍然可以嵌入类中,但这些类通常是 单例(singletons),这意味着应用程序中只有一个类的 实例(instance)。例如,单例 Printer 类可能具有 currentPrinter 等变量和 print() 等操作,但应用程序只有一个实例。即使只有一个实例在运行,将类使用的数据与作用于该数据上的操作封装在一起仍然是有益的。在其他情况下,通常以数据为中心(与以算法或服务为中心相反)的类会有多个实例。

这段话描述了一些设计模式:单例和多实例。即使不采用面向对象的思想,了解这些知识也是非常重要的。在模块化设计中,我们经常会遇到单一实例模块(single-instance module)和多实例模块(multiple-instance module),它们在封装模块的数据方式上,有着本质的区别。

对于单一实例模块,其数据以静态形式存在于 .c 文件中,并通过 .h 文件中提供的接口来访问这些数据。由于使用了静态数据,这种方法适用于只需要处理一套数据的模块。这种方式简单,简单意味着可靠。

当一个模块要为不同的客户管理不同的数据时,要使用多实例模块。在多实例模块中,必须要初始化数据结构并把它传回给客户以保持其上下文。比如一个环形缓冲区模块。

在面向对象编程中,单例是一种设计模式,其中确保一个类只有一个实例,并提供一个全局访问点来访问该实例。假如 Printer 类是一个单例,这意味着在整个应用程序中,只有一个 Printer 类的实例存在。

类生来具有一些特殊的操作:构造函数和析构函数。

在面向对象编程中,构造函数析构函数 是两个非常重要的成员函数:

  1. 构造函数在创建对象时自动调用,主要作用是初始化对象的成员变量和其他资源。在本书中,构造函数命名为 Xxxx_Init()。此外,在本书中,创建对象的函数命名为 Xxxx_Create(),在这个函数中调用构造函数 Xxxx_Init()
  2. 析构函数在销毁对象时自动调用,主要作用是释放对象所占用的资源,例如内存、文件句柄等,还可以执行一些清理操作,例如关闭文件、断开网络连接等。在本书中,析构函数命名为 Xxxx_Cleanup() 。此外,在本书中,销毁对象的函数命名为 Xxxx_Destroy(),在这个函数中调用析构函数 Xxxx_Cleanup()

相关文章:

书摘:C 嵌入式系统设计模式 04

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。 本系列描述我对书中内容的理解。 实现类的最简单方法是使用文件作为封装…...

C 练习实例16 - 最大公约数和最小公倍数

题目:输入两个正整数a和b,求其最大公约数和最小公倍数 数学:最大公约数*最小公倍数a*b 例如:a16,b20。最小公倍数80,最大公约数4。80*416*20。 算法:辗转相除法,又称欧几里德算法…...

GAN-概念和应用场景

概念和应用 生成对抗网络 (GAN) 的 18 个令人印象深刻的应用 by 杰森布朗利 on July 12, 2019 in 生成对抗网络110 鸣叫 共享 生成对抗网络 (GAN) 是一种用于生成建模的神经网络架构。 生成式建模涉及使用模型生成可…...

LeetCode(36)有效的数独 ⭐⭐

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图) 注…...

用LCD显示字符‘A‘

#include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 sbit RSP2^0; //寄存器选择位&#xff0c;将RS位定义为P2.0引脚 sbit RWP2^1; //读写选择位&#xff0c;将RW位定义为P2.1引脚 sbit EP2^2; //使能…...

Zookeeper相关问题及答案(2024)

1、ZooKeeper是什么&#xff1f;它的主要用途是什么&#xff1f; ZooKeeper 是一个由 Apache 预先开发和维护的开源服务器&#xff0c;用于协调分布式应用程序。它是一个集中式服务&#xff0c;为分布式应用提供一致性保障&#xff0c;配置管理&#xff0c;命名&#xff0c;同…...

1.大数据概述

目录 概述hadoophadoop 模块hadoop 发行版apache社区版本CDP(CDHHDP)其它云产商框架选择 hadoop 安装 结束 概述 先了解几个常用的网站 apache 官网hadoop 官网hadoop githubhttps://github.com/apache/xxx [https://github.com/apache/spark (example)] hadoop hadoop 模块…...

NGUI基础-Widget

目录 Widget是什么 Widget组件包含的属性 Pivot Depth Size snap Aspect Free Based on Width Based on Height Widget是什么 在Unity UI系统中&#xff0c;"Widget"是指UI元素的基类&#xff0c;它为UI元素提供了位置、大小和锚点等基本属性。通过使用&qu…...

SpringBoot集成沙箱支付

前言 支付宝沙箱支付&#xff08;Alipay Sandbox Payment&#xff09;是支付宝提供的一个模拟支付环境&#xff0c;用于开发和测试支付宝支付功能的开发者工具。在真实的支付宝环境中进行支付开发和测试可能涉及真实资金和真实用户账户&#xff0c;而沙箱环境则提供了一个安全…...

BUUCTF--gyctf_2020_borrowstack1

这是一题栈迁移的题目&#xff0c;先看看保护&#xff1a; 黑盒测试&#xff1a; 用户可输入两次内容&#xff0c;接着看看IDA中具体程序流程&#xff1a; 我们看到溢出内容只有0x10的空间给我们布局&#xff0c;这显然是不足以我们布置rop的。因此肯定就是栈迁移了。迁到什么地…...

图像分割-Grabcut法(C#)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的VB版本请访问&#xff1a;图像分割-Grabcut法-CSDN博客 GrabCut是一种基于图像分割的技术&#xff0c;它可以用于将图像中的…...

C# WPF上位机开发(Web API联调)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多时候&#xff0c;客户需要开发的不仅仅是一个上位机系统&#xff0c;它还有其他很多配套的系统或设备&#xff0c;比如物流小车、立库、数字孪…...

c语言:用结构体求平均分|练习题

一、题目 用c语言的结构体&#xff0c;求4位学生成绩的平均分 如图&#xff1a; 二、代码截图【带注释】 三、源代码【带注释】 #include <stdio.h> float aver();//声明平均分函数 void printScore();//声明打印函数 //设置结构体&#xff0c; struct student { …...

echarts 仪表盘进度条 相关配置

option {series: [{type: gauge,min: 0,//最大值max: 100, //最小值startAngle: 200,//仪表盘起始角度。圆心 正右手侧为0度&#xff0c;正上方为90度&#xff0c;正左手侧为180度。endAngle: -20,//仪表盘结束角度splitNumber: 100, //仪表盘刻度的分割段数itemStyle: {color…...

Simpy:Python之离散时间序列仿真

Simpy&#xff1a;Python之离散时间序列仿真 文章目录 Simpy&#xff1a;Python之离散时间序列仿真简介基本使用语法简单案例在数据中心中的应用案例 简介 下载地址网站&#xff1a; https://pypi.org/project/simpy/ 有关教程网站&#xff1a; https://simpy.readthedocs.…...

连接GaussDB(DWS)报错:Invalid or unsupported by client SCRAM mechanisms

用postgres方式连接GaussDB(DWS)报错&#xff1a;Invalid or unsupported by client SCRAM mechanisms 报错内容 [2023-12-27 21:43:35] Invalid or unsupported by client SCRAM mechanisms org.postgresql.util.PSQLException: Invalid or unsupported by client SCRAM mec…...

汽车标定技术(十四)--标定数据固化方法简介

目录 1.标定数据固化方法 1.1 基于XCP固化 1.2 基于UDS固化 2. 具体实现形式 2.1 CAN...

2024年关键技术发展战略趋势前瞻

技术趋势在不断变化&#xff0c;但总的趋势是技术日益深入人类生活的方方面面&#xff0c;这些趋势可能会对未来的科技发展和人类生活产生深远影响&#xff0c;以下是预计今年将塑造未来的一些关键技术趋势。 更多的人将采用人工智能和机器学习 人工智能(AI)和机器学习(ML)不…...

Java程序设计——GUI设计

一、目的 通过用户图形界面设计&#xff0c;掌握JavaSwing开发的基本方法。 二、实验内容与设计思想 实验内容&#xff1a; 课本验证实验&#xff1a; Example10_6 图 1 Example10_7 图 2 图 3 Example10_15 图 4 设计思想&#xff1a; ①学生信息管理系统&#xff1a…...

three.js Raycaster(鼠标点击选中模型)

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...