0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

隐藏结构体成员的方法与问题

奈因PCB电路板设计 来源:最后一个bug 作者:bug菌 2021-08-11 10:18 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

今天主要跟大家分享一种隐藏结构体成员的方法,很多地方也叫“不完全类型”,所以这里bug菌以更加通俗易懂的方式跟大家介绍下,并且谈一谈相关的一些问题。

1

引出话题

首先我们来看下面一个最简单的例子:

参考代码:

1/************filename:

App.h*************/ 2#ifndef __APP_H__ 3#define __APP_H__ 4 5 6typedef struct _tag_StObj stObj; 7struct _tag_StObj 8{ 9 int member1;

10 int member2;

11};

12 13//interface

14 15int sAdd(stObj *pObj); 16 17#endif 18 19/************filename: App.c*************/ 20#include “App.h” 21 22/**********************************

23 * Function : sAdd 24 * Note :加法函数,也是接口函数 25 * Author: bug菌

26 **********************************/ 27int sAdd(stObj *pObj) 28{ 29 return (pObj-》member1 + pObj-》member2); 30} 31 32/************filename: main.c*************/ 33#include 《stdio.h》 34#include

“。/App/App.h” 35 36int main(void) 37{ 38 stObj Obj; 39 Obj.member1 = 1;

40 Obj.member2 = 2; 41 42 printf(“result = %d ”,sAdd(&Obj)); 43 44 return 0; 45}

以上是三个文件中的内容,程序编译通过,输出结果为3。在main函数中均可以通过结构体定义变量,并且直接访问其结构体内部的成员,而很多人觉得结构体作为一个对象不应该把其内部数据全部暴露出来供开放访问,非常不利于内部实现细节的封装和对象数据的安全性。那有什么办法不允许外部访问结构体成员呢?

2

不完全类型

“不完全类型”看起来很深奥的名字,主要还是翻译问题吧,从字面上来说就是不那么完整的类型,我们知道像常规的char,int,float类型,要作为一个类型,那么平台肯定为他们提供了所占据的内存大小和处理方式,而不完全类型几乎没有在定义的时候给出,比如没有指定长度的数组array[],他也是一种不完全类型,虽然表示的是数组,可是你不知道它到底有多大,这样编译器就不能够为其分配内存而定义报错。下面修改下之前的程序,把结构体定义放到对应的app.c文件,而app.h中留下一个啥也不含的同名结构体“空壳”。

1/************filename: App.h*************/ 2#ifndef __APP_H__ 3#define __APP_H__ 4 5 6typedef struct _tag_StObj stObj;

7/*struct _tag_StObj 8{ 9 int member1;

10 int member2; 11};*/ 12 13//interface 14 15int sAdd(stObj *pObj);

16 17#endif 18 19/************filename: App.c*************/ 20#include “App.h” 21 22struct _tag_StObj 23{ 24 int member1; 25 int member2; 26};

27/********************************** 28 * Function : sAdd 29 * Note :加法函数,也是接口函数 30 * Author:

bug菌 31 **********************************/ 32int sAdd(stObj *pObj) 33{ 34 return (pObj-》member1 + pObj-》member2);

35} 36 37/************filename: main.c*************/ 38#include 《stdio.h》 39#include “。/App/App.h” 40 41int main(void) 42{ 43 stObj Obj;

44 Obj.member1 = 1; 45 Obj.member2 = 2;

46 47 printf(“result = %d ”,sAdd(&Obj)); 48 49 return 0; 50}

编译结果:

此时编译器会报一个error,表示不知道该结构体到底是多大,如果你要是问App.c文件里面不是定义了结构体成员吗?怎么还会报错?你需要看一下bug菌的往期精彩,C程序的编译都是以源文件为单元展开的。

3

求助指针

把前面的main.c改改看能不能编译通过:

1/************filename: main.c*************/ 2 3#include 《stdio.h》 4#include “。/App/App.h” 5 6int main(void) 7{ 8 stObj *Obj; 9 //Obj.member1 = 1;

10 //Obj.member2 = 2; 11 12 printf(“result = %d ”,sAdd(Obj)); 13 14 return 0; 15}

然而此时编译通过:

当然上面程序语法没问题,运行却是有问题的,定义了一个野指针,一旦运行基本上都会奔溃。并且不能通过指针直接访问结构体成员,因为这是一个不知道成员的结构体“空壳”,同样sizeof也检测不了大小。

那问题来了,为什么用结构体定义变量不行,而定义成指针却可以呢?其实这个问题与bug菌之前谈到的可以定义成void*指针变量,却不能定义为void变量是相同的道理,因为指针的大小一般平台和编译器确定下来就基本确定下来了,它不依赖于所指向的对象类型,同样void也是一个不完全类型。

4

隐藏结构体成员

现在遵循两个原则:1、不能直接用不完全类型定义变量,可以定义指针:2、不能够访问其结构体内部成员,因为根本不知道。

参考代码:

1/************filename: App.h*************/ 2#ifndef __APP_H__ 3#define __APP_H__ 4 5 6typedef struct _tag_StObj stObj;

7 8//interface 9stObj * sCreate(int member1,int member2); 10int sAdd(stObj *pObj);

11 12 13#endif 14 15/************filename: App.c*************/ 16#include “App.h” 17 18struct _tag_StObj 19{ 20 int member1; 21 int member2; 22}; 23 24/********************************** 25 * Function : sCreate 26 * Note :创建函数,也是接口函数 27 * Author: bug菌 28 **********************************/ 29stObj * sCreate(int member1,int member2) 30{ 31 static stObj staticObj;

32 33 staticObj.member1 = member1; 34 staticObj.member2 = member2; 35 36 return &staticObj; 37} 38 39 40/********************************** 41 * Function : sAdd 42 * Note :加法函数,也是接口函数 43 * Author: bug菌 44 **********************************/ 45int sAdd(stObj *pObj) 46{ 47 return (pObj-》member1 + pObj-》member2);

48} 49 50/************filename: main.c*************/ 51 52#include 《stdio.h》 53#include “。/App/App.h” 54 55int main(void) 56{ 57 stObj *Obj; 58 59 Obj = sCreate(3,5); //内部构造结构体

60 61 printf(“result = %d ”,sAdd(Obj)); //调用相应的接口 62 63 return 0; 64}

编译成功,运行OK,结果如下:

那么不完全类型隐藏结构体成员的目的基本上就达到了,以后外部也是无法通过结构体变量直接访问成员了,只能对象自身在相应的.c文件中定义对应的接口,然后声明在对应的interface中供外部使用。

5

but

那么我们回过头来想想这样的不完全类型究竟做了啥?1)不允许外部访问数据细节,因为这个类型不完整,编译器把握不住~2)全程通过指针传递,本质上和void*差别不大,但是他可以进行类型的检查,这样代码的数据意义更加的明确。

当我们使用不完全结构体类型,结构体所有的成员都变成了私有,即这一种封装私有数据的方式,且均需要通过相应的接口函数访问,确实一种好的面向对象的封装方式。但是完全私有的封装还是比较麻烦,还是要做到“公私分明”,函数调用也需要一定的开销,就看工程师们怎么去平衡“性价比”了。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5186

    文章

    20143

    浏览量

    328686
  • 结构体
    +关注

    关注

    1

    文章

    131

    浏览量

    11296

原文标题:如何隐藏"结构体对象"成员?

文章出处:【微信号:pcbgood,微信公众号:奈因PCB电路板设计】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    共用声明

    共用也称联合体。 和结构还是有点像: union 共用名称 { 成员1; 成员2
    发表于 12-05 07:24

    为什么不建议用匿名结构

    : invalid use of ‘struct data_def::::value_bit’ 有可能有方法可以设置 gcc 编译支持匿名结构,但是鱼鹰也不想深究,改了就是。 因此,为了代码的通用性
    发表于 12-04 07:39

    C语言的编程技巧

    1、宏定义使用do{...}while(0)‌:当宏定义中包含多条语句时,使用do{...}while(0)可以避免语句嵌套问题,确保宏的独立性。‌ ‌2、灵活数组成员‌:C99标准允许结构的最后
    发表于 11-27 06:46

    C语言结构使用

    型的数据组合。 结构的声明与定义 结构的声明一般形式为: c struct 结构名{
    发表于 11-12 08:30

    can_sample例程,rxmsg.hdr = -1;语句报错如何解决?

    使用官方CAN_sample例程编译,cubemx已经配置好CAN引脚,menuconfig也已经打开相关接口,但编译时报错,显示结构 rt_can_msg结构中没有hdr这个
    发表于 09-24 07:05

    云加速是如何隐藏源服务器ip的

    服务器IP是保护服务器的一项重要安全措施。 华纳云 为大家分享受一下内容: 隐藏源服务器IP的主要目的是防止恶意攻击者通过直接访问服务器IP地址来发动攻击,同时提高服务器的隐私性和安全性。以下是一些常见的方法: 反向代理:云加速服务提供商会在源
    的头像 发表于 09-12 16:31 428次阅读

    定义IO初始化结构

    由上述IOPORT相关功能的枚举类型我们可以知道,在对IOPORT模块进行初始化时需要根据情况配置它们。因此我们定义一个IOPORT初始化的结构类型IOPORT_Init_t,它的成员包括了由上述所有枚举类型所声明的变量,因此
    的头像 发表于 07-16 16:26 1102次阅读

    材料导热系数测试方法及应用

    材料特殊的半固态特性(易流动、易变形、接触热阻大)给测试带来挑战。本文将系统介绍适用于膏材料的导热系数测试方法。一、实验步骤1、实验设备DZDR-S导热系数测
    的头像 发表于 06-16 14:35 479次阅读
    膏<b class='flag-5'>体</b>材料导热系数测试<b class='flag-5'>方法</b>及应用

    渗压计在混凝土结构中的安装指南

    在现代土木工程和岩土工程中,渗压计是监测混凝土结构体内孔隙水压力变化的重要工具。南京峟思公司生产的渗压计因其高精度和可靠性而被广泛应用于各种工程监测项目中。一、渗压计在混凝土结构中的应用价值渗压计
    的头像 发表于 05-28 10:55 377次阅读
    渗压计在混凝土<b class='flag-5'>结构</b><b class='flag-5'>体</b>中的安装指南

    GLAD应用:全息光栅模拟

    成像的衍射元件,可以使得三维物场信息按照光学断层切片方式逐片地重构成像,不同的断层切片对应于三维物空间上轴向的不同位置。因此,采用全息成像方法既可以研究静态物体的高度与外形轮廓的变化,以及半透明物体
    发表于 05-15 09:32

    程序设计与数据结构

    《程序设计与数据结构》重点阐述了三大方向内容: 1. C语言学习中的痛点:针对当前工程师在C语言学习中的痛点,如指针函数与函数指针,如何灵活应用结构等。从变量的三要素(变量的类型,变量的值和变量
    发表于 05-13 16:45

    C语言中结构与联合体的深度解析:内存布局与应用场景

    一、基础概念与核心差异 1.1 结构(Struct)的本质 **结构是C语言中实现数据封装的基石,其核心特征在于内存独立性。每个成员变量
    发表于 04-08 09:18

    采购GUTOR UPS备品备件,隐藏的“雷区” 你了解吗?

    在GUTOR UPS备品备件采购之路上,困难重重,选型、渠道甄别、成本把控、安装部署、售后保障,桩桩件件都是棘手难题。隐藏的“雷区” 你了解吗?
    发表于 03-21 16:08

    联想一机B5040拆解方法

    本文详细记录着联想一机B5040的拆卸方法
    发表于 03-20 18:04 0次下载

    BP神经网络的网络结构设计原则

    BP(back propagation)神经网络是一种按照误差逆向传播算法训练的多层前馈神经网络,其网络结构设计原则主要基于以下几个方面: 一、层次结构 输入层 :接收外部输入信号,不进行任何计算
    的头像 发表于 02-12 16:41 1248次阅读