电子产业一站式赋能平台

PCB联盟网

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

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

[复制链接]

570

主题

570

帖子

4308

积分

四级会员

Rank: 4

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

g1mrf0z5gz56401463941.jpg

g1mrf0z5gz56401463941.jpg

* w. J' t% B: w$ W9 d0 V模块使用者如果想通过某些简单直接粗暴的方式,去修改模块的各个属性参数,是一件轻而易举(技术上也是合情合理)的事情,因为根据接口头文件的最小信息公开原则,放在头文件的信息内容,难道不是公开且供大家放心使用的么?~
8 A; F' r" w$ |7 l: K(此刻,作者我,无言以对。。。)8 y! X8 C8 l3 ]6 n' S  B7 j3 C
鉴于key_module.h接口头文件显现出来的设计不足,我们可以使用掩码结构体对其进行改进,例如,对于原来的key_t结构体,我们可以把私有不公开的成员,放在struct __key里面,然后 key_t 结构体则改进成如下图所示的方式。
2 _$ g+ j9 o' [9 ^1 ~

cklz3nss4e46401464041.jpg

cklz3nss4e46401464041.jpg
! ]# D5 `. \( c6 }( i. E
然而,这种改进并未能在真正意义上掩盖住私有成员(struct __key的信息依然表露无遗),因此,我们参考“真刀真枪模块化(2.5)--君子协定”这篇文章,可以通过宏定义技法,把私有成员结构体的信息,真正隐藏起来,如下图所示。
7 N$ Y% s( t# F* @

cudmtmjsq3k6401464141.jpg

cudmtmjsq3k6401464141.jpg
# |2 F- g; |4 ?+ ]& D5 U) _# U8 S7 @$ T' l
使用以上宏定义,那么我们可以继续对struct __key结构体作出进一步的改进,把结构体的声明和成员定义,都交给了预编译宏进行处理,具体代码如下图所示。" X4 L" G& N# K; y* v5 b9 a

qn231nawriv6401464241.jpg

qn231nawriv6401464241.jpg

. l$ ^- o, @6 l2 G6 T* k当我们需要提取结构体成员进行使用的时候,可以使用CLASS_INTERNAL宏,该宏展开后是一种强制类型转换,目的是可以通过已知类型的结构体变量,来显式调用结构体成员,使用方式如下图所示。2 Y- A7 J4 P3 d& x( B8 S

v5b3us1sxp26401464341.jpg

v5b3us1sxp26401464341.jpg

# j" e, y' ]: K, V, B以上,就是使用掩码结构体技法对单片机按键模块的简单改进(以上截图多数为伪代码,提供一种思路),在实际的工程项目里面,推荐直接使用PLOOC,这个开源项目已经很完美地为C语言面向对象开发提供了必要的OOPC模板。
! [: P+ s8 w% e7 m/ d感谢阅读。
2 ^4 A2 H$ W3 r' ^/ g- q-END-$ \0 r0 ~+ s8 H% f4 ~6 I
往期推荐:点击图片即可跳转阅读* v2 H4 E$ v4 S* _% V
5 m$ M. Q! G( z# i
                                                        % }  r+ H: ~  l" D
                                                                # r. \- {( y: k; a$ D  p
                                                                        & p8 p2 ^2 u, i  r- X9 N: D9 m
                                                                                & C5 R  _% B6 j1 u, ]; H3 H

bwtoc2jyina6401464441.jpg

bwtoc2jyina6401464441.jpg

" c' b8 J+ v) Z                                                                               
1 ^; X6 E! N: B                                                                                        嵌入式用 C 语言进行面向对象开发,从未试过如此简单!
$ ~% ]* P& |& B/ I% X( C7 ]$ C7 h                                                       
$ L: [; z9 n5 g: Z$ b                                                               
- i# F: {! ]- m% n                                                                        ; O  ~% g- X' e. \. U4 c
                                                                                ' x# `) `3 i0 G" S$ W

woq4z2qgx3b6401464541.jpg

woq4z2qgx3b6401464541.jpg
- @5 L# A: {/ G! V
                                                                                ; E( c7 f6 @0 Z6 k
                                                                                        嵌入式 C 语言 struct,面向对象编程的第一步. W$ Y# D6 B3 M, R
                                                               
6 c# \$ W" @( ^& u2 g                                                                       
- s. G4 n4 s5 j  i1 a6 T                                                                               
& w4 H7 A2 [" d3 H8 ]

mdyda0fusq06401464641.jpg

mdyda0fusq06401464641.jpg
+ W: t5 l4 a% w8 h8 a" ?" b
                                                                               
, U0 j* J. C) k4 r9 R' f+ ^                                                                                        面向对象的编程思维- {4 M: K! E/ l+ D: d
                                                                                ( {0 O' M7 N0 c6 v; l/ R9 Q- v: ^
                                                                       
1 G' d4 w0 n. R" R, m                                                               
' ]- n( ^) z* S3 e1 d* Z- h( b                                                        我是老温,一名热爱学习的嵌入式工程师( o6 T( T3 O: c2 C3 e5 b4 I
关注我,一起变得更加优秀!
回复

使用道具 举报

发表回复

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

本版积分规则


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