电子产业一站式赋能平台

PCB联盟网

搜索
查看: 222|回复: 0
收起左侧

嵌入式 C 语言知识点,掩码结构体

[复制链接]

570

主题

570

帖子

4308

积分

四级会员

Rank: 4

积分
4308
发表于 2024-7-9 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师1 x1 m/ [2 V- K( v  k/ Z
关注我,一起变得更加优秀!前面的一系列技术文章,我们都曾多次充分说明了,在设计业务逻辑复杂的嵌入式软件时,最好以面向对象作为基本的设计思想,对各个功能模块尽可能地做好封装与解耦。关于嵌入式 C 语言面向对象设计的文章,可以点击以下链接进行回顾:
! p( z$ ]6 e4 H7 t5 c基于状态机和面向对象的思想,设计一个通用的按键检测模块。
, q' r$ a2 d3 F8 C1 F基于面向对象和简单工厂模式,设计一个通用的 LED 显示模块。
9 Z( H/ X8 a/ ~4 j7 b6 a* h# ~嵌入式 C 语言面向对象编程 --- 总结' F! A9 w6 _" m" n/ w% s- e' e9 x# {5 c
面向对象是一种基本的设计思想,与所采用的编程语言基本无关(如果非要杠汇编和二进制,那就是你对),一个反面的例子就是,很多人在初学C++的时候,即便C++里面集成了很多面向对象设计的语法糖,但初学者依然会很容易把“类”当作结构体使用。. ~: k- k" z4 B+ [/ E6 ?
面向对象的基本出发点是:把“数据属性”与“数据属性的处理方法”都封装在一起。而我们在使用 C 语言进行嵌入式功能模块设计的时候,因为C语言并不具备C++语言的语法糖,所以通常都会使用结构体的方式来模拟类的设计。
% E2 o  K1 k$ c/ l( g3 X# G6 z因此,我们在使用OOC(Object-Oriented C Programming with ANSI -C)技术的时候,通常都会面临以下问题:* h; y. S# ]6 g- I! n0 S6 [* X% E" {' ]
“嗯,我们可以使用结构体来模拟类,把所有数据变量和函数指针都放在结构体里面进行封装,并且把这个结构体放在接口头文件里面,那么问题来了,结构体里面的成员都是public的(语法层面可以直接使用),但某些数据变量却是private属性(不允许被模块外部直接调用)”
2 D7 S# `- j: R$ j5 p6 x# q那么,应该如何解决这个问题呢?# a  ~( `# T& ?2 M+ o
在我以往编写的 C 语言面向对象文章里面,示例代码的接口头文件,通常都伴随着这个“直接且尖锐”的问题,而通过编码和模块引用规范这一系列的“君子协定”,往往只能起到“防君子而不能防小人”的作用。3 i+ N) s: H! ]4 I! u2 ^
直到最近,我看了傻孩子大佬(公众号:裸机思维)的一系列文章才知道,原来C语言里面有一种技法,掩码结构体(Masked Structure),可以为结构体里面的private属性变量盖上一层蒙版,模块使用者即使看到了结构体的私有数据变量,也不能对其进行外部直接访问调用。  a" e- d. X2 E$ t
在通用的单片机按键检测模块这篇文章里面,对于模块的接口头文件 key_module.h,里面两个最主要的结构体,key_t和key_manager_t,其内部大量暴露了模块的私有参数变量,如下图所示。9 a3 o8 p& j2 W* l7 S  L

4x1azzdqhta6405245325.jpg

4x1azzdqhta6405245325.jpg

( ^# F, M. ]; a: g7 i# i模块使用者如果想通过某些简单直接粗暴的方式,去修改模块的各个属性参数,是一件轻而易举(技术上也是合情合理)的事情,因为根据接口头文件的最小信息公开原则,放在头文件的信息内容,难道不是公开且供大家放心使用的么?~3 z: L: p. d- _$ J" p8 g
(此刻,作者我,无言以对。。。); E: d# q( ]9 b; j" P  y+ X$ I
鉴于key_module.h接口头文件显现出来的设计不足,我们可以使用掩码结构体对其进行改进,例如,对于原来的key_t结构体,我们可以把私有不公开的成员,放在struct __key里面,然后 key_t 结构体则改进成如下图所示的方式。
8 q( H- H/ G2 G  h

ufmhia4fgkw6405245425.jpg

ufmhia4fgkw6405245425.jpg
8 _3 c9 c4 J! ]8 C. Z
然而,这种改进并未能在真正意义上掩盖住私有成员(struct __key的信息依然表露无遗),因此,我们参考“真刀真枪模块化(2.5)--君子协定”这篇文章,可以通过宏定义技法,把私有成员结构体的信息,真正隐藏起来,如下图所示。3 f, y  E/ d& E

42grfbjlvcy6405245525.jpg

42grfbjlvcy6405245525.jpg

  o3 e% e2 D2 k' D* x9 k' j$ K使用以上宏定义,那么我们可以继续对struct __key结构体作出进一步的改进,把结构体的声明和成员定义,都交给了预编译宏进行处理,具体代码如下图所示。. v5 r/ o* ?) S' q$ V4 B9 F6 d% O, U

1rsj4op4kdn6405245625.jpg

1rsj4op4kdn6405245625.jpg
7 R. [6 @, C# V5 l) M& n; r. }
当我们需要提取结构体成员进行使用的时候,可以使用CLASS_INTERNAL宏,该宏展开后是一种强制类型转换,目的是可以通过已知类型的结构体变量,来显式调用结构体成员,使用方式如下图所示。
( t5 w) h# h) L+ E* {

vslywbt0hpq6405245725.jpg

vslywbt0hpq6405245725.jpg
3 M8 N3 P% d0 g' T" v5 }& X. v  J
以上,就是使用掩码结构体技法对单片机按键模块的简单改进(以上截图多数为伪代码,提供一种思路),在实际的工程项目里面,推荐直接使用PLOOC,这个开源项目已经很完美地为C语言面向对象开发提供了必要的OOPC模板。
$ B: H# t: |( z6 g2 {感谢阅读。
: G8 \* T. x' e  }0 s-END-" ^3 m2 n1 g) b
往期推荐:点击图片即可跳转阅读5 l" `' M, M( t% N) n( p
) q3 M6 w0 L- [4 G/ F( z
                                                       
3 }- U+ |4 Q9 N, m7 y: X                                                                ' G; v/ F+ ?' v  x
                                                                       
* |! p. \) U  G3 V                                                                                ( L' ]1 w0 r. v

tpcxvajfi426405245825.jpg

tpcxvajfi426405245825.jpg

3 o- R  W8 ~  h: S1 j                                                                                4 C0 s9 L9 j9 ^. g
                                                                                        嵌入式用 C 语言进行面向对象开发,从未试过如此简单!: I3 F# l2 l6 M" |
                                                       
) p( ]* _* z; v! C, @  d                                                               
# [+ O/ V) i# j                                                                       
8 |, D4 D" g+ H* Y. T' N                                                                                ; |4 Y: X& t2 s! e7 g

5sl02ljdt1j6405245925.jpg

5sl02ljdt1j6405245925.jpg
, D6 L! L; p- B8 U; c+ w5 ?# U
                                                                               
' k- U6 p( O+ m2 V                                                                                        嵌入式 C 语言 struct,面向对象编程的第一步
; s9 M" Q: e# _# e: V                                                                - H3 d+ |. `$ q/ S; P7 n3 k' T
                                                                        , S  D3 L9 T! j; q9 _7 O. ]4 W! J
                                                                               
/ ]  r6 L/ Z  b) ]- ]$ S1 w) L/ a1 |

okx1hvk35x26405246025.jpg

okx1hvk35x26405246025.jpg

* r) C* A; j: [4 T                                                                                5 v1 j* m; S# d+ ^# y
                                                                                        面向对象的编程思维0 _$ S7 g& X# g
                                                                               
1 s! p( {. `0 I2 v                                                                          |# Q% D/ O# N, M5 M/ p7 R4 U6 {
                                                               
$ P0 z6 V- F# K* k                                                        我是老温,一名热爱学习的嵌入式工程师
6 W0 o5 U+ ]- T9 S关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表