当前位置: 首页 > 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之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Psychopy音频的使用

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

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...